十二棵橡树

实现 Fetch 超时管理功能

橡树上2020-12-05

目录

前言

对比 Ajax 和 Fetch一文中提到,Fetch API 是没有内置的 timeout 超时管理功能的,但现实项目中如果需要这个功能,该怎么实现呢?

实现

Fetch API 自身是基于 Promise 模型的,所以可以从 Promise 上着手。

在 Promise 中,有一个 Promise.race(iterable) 方法,一旦迭代器中的某个 promise 解决或拒绝,返回的 promise 就会解决或拒绝:

const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, 'one');
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'two');
});

Promise.race([promise1, promise2]).then((value) => {
  console.log(value);
  // Both resolve, but promise2 is faster
});

以此为基础,则可以给 Fetch 搭配一个新的定时 promise 和 AbortController,用于在超时的时候取消请求并切换整个流程:

function fetchWithTimeout(url, param, timeout) {
  // abortcontroller
  const controller = new AbortController()
  // 超时 promise
  const timeoutPromise = (timeout) => new Promise((resolve, reject) => {
    setTimeout(() => {
      // 超时响应信息
      const response = new Response(
        JSON.stringify({
          code: 1,
          msg: `timeout ${timer}s`
        })
      );
      reslove(response); //  reslove 流程
      controller.abort(); // 发送终止信号
    }, timeout)
  })
  // 请求 promsie
  const fetchPromise = fetch(url, {
    signal: signal //设置信号
    ...prama
  })
  // 返回一个 Promise.race
  return Promise.race([
    timeoutPromise(timeout),
    fetchPromise
  ])
}