最近用 @kmi 框架的时候,注意到其封装的 request 函数有如下代码:

 1const request: IRequest = (url: string, opts: any = { method: "GET" }) => {
 2  return new Promise((resolve, reject) => {
 3    querySomething()
 4        handleResponse(res);
 5      })
 6      .catch((error) => {
 7        try {
 8          handler(error, opts, config);
 9        } catch (e) {
10          reject(e);
11        }
12      });
13  });
14};

代码大意为:

  1. 执行某个封装好的异步请求 querySomething
  2. 捕获异常
  3. 将异常扔给 handler 处理

此处省略了正确执行的时候进行 resolve 操作,只保留了 reject 的逻辑。

问题在于:假设 handler 函数成功运行,那么当前的 Promise 对象状态就不会被更新,保持 pending 状态不变。

假设某个组件调用了 request 方法,运行时报错了,由于 Promise 对象状态一直保留在 Pending,后续代码永远不会被执行。

思考 Link to heading

改变 Promise 通常的使用方式,在此处似乎是有道理的:保证请求被统一的处理函数接管,除非处理函数本身出错,否则不报错。

但是如果不了解这一特性的开发者使用 request 函数后,可能会对自己代码逻辑不运行产生疑惑;另一方面,需要开发者在使用 request 请求时,即使 request 之后的代码不运行也不影响正常的代码逻辑。