我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

继续fetch或者axios请求远程接口的话题,本文侧重于虚拟服务器端的逻辑。所有服务器端的逻辑,都放在本地执行。这种方案,主打的就是一个timeout可控。因为在一些场景下,多久能够解析到接口的返回值,这是个非常重要的问题,需要反复测试。而传统的方案组合里面,对timeout时间的掌控就相对不靠谱多了。

苏南大叔:NodeJs及浏览器环境,如何应对虚拟请求远程接口的需求? - timeout请求远程接口
NodeJs及浏览器环境,如何应对虚拟请求远程接口的需求?(图1-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程经验文章。测试环境:chrome@131.0.6778.70nodejs@20.18.0。本文的主要内容,在以前的文章里面也有提及,这里仅仅是个再次总结梳理的文章。对于本文是模拟的get还是post来说,一样都一样。getpost请求的区别不在这里。

前文回顾

前文回顾,很多篇文章都写过使用setTimeout()精准模拟接口返回的事情,参考:

其核心的技术方案,除了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经验文章,请参考:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   js