NodeJs及浏览器环境,如何应对虚拟请求远程接口的需求?
发布于 作者:苏南大叔 来源:程序如此灵动~继续fetch
或者axios
请求远程接口的话题,本文侧重于虚拟服务器端的逻辑。所有服务器端的逻辑,都放在本地执行。这种方案,主打的就是一个timeout
可控。因为在一些场景下,多久能够解析到接口的返回值,这是个非常重要的问题,需要反复测试。而传统的方案组合里面,对timeout
时间的掌控就相对不靠谱多了。
苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程经验文章。测试环境:chrome@131.0.6778.70
,nodejs@20.18.0
。本文的主要内容,在以前的文章里面也有提及,这里仅仅是个再次总结梳理的文章。对于本文是模拟的get
还是post
来说,一样都一样。get
和post
请求的区别不在这里。
前文回顾
前文回顾,很多篇文章都写过使用setTimeout()
精准模拟接口返回的事情,参考:
- https://newsn.net/say/react-await.html
- https://newsn.net/say/react-defer.html
- https://newsn.net/say/react-useloaderdata.html
其核心的技术方案,除了setTimeout()
外,还包括promise
的使用,参考:
仅模拟timeout
网上最流行的方案里面,基本上都是这么写的。尽管看起来比较不严谨。但是,贵在代码简单迅速精准解决问题。适用于对【网络请求】不敏感,对【时间把控】敏感的情形。
模拟代码一,参考代码:
const fetchDataFake = () => {
return new Promise((r) => {
setTimeout(() => {
r({ name: "苏南大叔" });
}, 3000);
});
};
模拟代码二,当然,也可以再精细一点:
function fetchDataFake() {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve({
code: 1,
data: { id: Date.now().toString().slice(-6), name: "苏南大叔" },
});
} else {
reject({ code: 0, message: "第一种错误方式" }); //可以兼容Error的情况了
// reject(new Error("第二种错误方式")); //可以兼容Error的情况了
// throw new Error("第三种错误方式") // 这个不行,不能这么干,直接开大
}
}, 1000);
});
}
后续的代码(不变的部分):
(async () => {
let aa = await fetchDataFake().catch((e)=>{
return { code: -999, data: e.message };
}); // react的userequest里面,不需要这个catch
console.log(aa);
})();
模拟timeout和response
上面的方案里面,主要强调了timeout
。实际上并没有考虑网络请求需要两个.then
才能处理的问题,也就是说有较大的概率下,上线的时候除了要替换这个虚拟请求函数外,还得替换下一步处理的代码。
所以,这里本地模拟一个Response
对象。那么,一个Response
对象是什么样的呢?在上一篇文章里面曾经留了个坑。
模拟response
(不完美,待完善):
function getResponse(_json, ok_bool = true) {
// 没有规定response的内容必须是json,但是我这个程序里面需要json
let message = "";
if (typeof _json !== "string") {
message = JSON.stringify(_json);
} else {
_json = JSON.parse(_json);
}
return {
ok: ok_bool,
// status: ok_bool ? 200 : 500, // 确实有status,但是代码里面没有用到
message: message, // message永远都是string
json: function () {
return Promise.resolve(_json);
},
text: function () {
return Promise.resolve(message);
},
};
}
这块儿写成class MyResponse(){}
的样子,应该会更好理解一些。
模拟网络请求,代码:
function fetchDataFakePromise() {
// 真实请求
// return fetch("http://localhost:3222/get");
// 模拟请求
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve(
getResponse({
code: 1,
data: { id: Date.now().toString().slice(-6), name: "苏南大叔" },
})
);
} else {
reject(getResponse({ code: 0, message: "网络错误" }, false));
}
}, 2000);
});
}
处理接口返回值(相对不动的部分):
function fetchDataFake() {
return fetchDataFakePromise().then(async (response) => {
if (!response.ok) {
// throw new Error("Failed to fetch data");
throw new Error(await response.text());
}
return response.json();
});
// .catch((error) => {
// // 这里的message极有可能就是 Failed to fetch data
// // 否则理论上来说,走不到这里
// // 这里return的话,对于下一步来说,也是success,而不是error
// // react的uesrequest,不需要catch
// return { code: -999, message: error.message };
// });
}
(async () => {
let ret = await fetchDataFake();
console.log(ret);
})();
结语
本文的代码,和网络上流传的代码存在较大差异,增加了苏南大叔对response
对象的理解。如果您对苏南大叔的代码不认可,可以留言指出问题所在。更多苏南大叔的JavaScript
经验文章,请参考:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。