我有一个fetch-api POST请求:

fetch(url, {
  method: 'POST',
  body: formData,
  credentials: 'include'
})

我想知道这个的默认超时时间是多少?我们如何将它设置为特定的值,比如3秒或不定秒?


当前回答

使用AbortController和setTimeout;

const abortController = new AbortController();

let timer: number | null = null;

fetch('/get', {
    signal: abortController.signal, // Content to abortController
})
    .then(res => {
        // response success
        console.log(res);

        if (timer) {
            clearTimeout(timer); // clear timer
        }
    })
    .catch(err => {
        if (err instanceof DOMException && err.name === 'AbortError') {
            // will return a DOMException
            return;
        }

        // other errors
    });

timer = setTimeout(() => {
    abortController.abort();
}, 1000 * 10); // Abort request in 10s.

这是@fatcherjs/middleware-aborter中的一个片段。

通过使用fatcher,可以很容易地中止取回请求。

import { aborter } from '@fatcherjs/middleware-aborter';
import { fatcher, isAbortError } from 'fatcher';

fatcher({
    url: '/bar/foo',
    middlewares: [
        aborter({
            timeout: 10 * 1000, // 10s
            onAbort: () => {
                console.log('Request is Aborted.');
            },
        }),
    ],
})
    .then(res => {
        // Request success in 10s
        console.log(res);
    })
    .catch(err => {
        if (isAbortError(err)) {
            //Run error when request aborted.
            console.error(err);
        }

        // Other errors.
    });

其他回答

更新,因为我最初的答案有点过时,我建议使用像这里实现的中止控制器:https://stackoverflow.com/a/57888548/1059828或看看这个非常好的帖子解释中止控制器与fetch:我如何取消HTTP fetch()请求?

过时的原答案:

我非常喜欢使用Promise.race这种简洁的方法

fetchWithTimeout.js

export default function (url, options, timeout = 7000) {
    return Promise.race([
        fetch(url, options),
        new Promise((_, reject) =>
            setTimeout(() => reject(new Error('timeout')), timeout)
        )
    ]);
}

main.js

import fetch from './fetchWithTimeout'

// call as usual or with timeout as 3rd argument

// throw after max 5 seconds timeout error
fetch('http://google.com', options, 5000) 
.then((result) => {
    // handle result
})
.catch((e) => {
    // handle errors and timeout error
})

使用c-promise2库,可取消的获取超时可能像这样(Live jsfiddle演示):

import CPromise from "c-promise2"; // npm package

function fetchWithTimeout(url, {timeout, ...fetchOptions}= {}) {
    return new CPromise((resolve, reject, {signal}) => {
        fetch(url, {...fetchOptions, signal}).then(resolve, reject)
    }, timeout)
}
        
const chain = fetchWithTimeout("https://run.mocky.io/v3/753aa609-65ae-4109-8f83-9cfe365290f0?mocky-delay=10s", {timeout: 5000})
    .then(request=> console.log('done'));
    
// chain.cancel(); - to abort the request before the timeout

这段代码作为一个npm包cp-fetch

在取回API中还没有超时支持。但这可以通过一个承诺来实现。

如。

  function fetchWrapper(url, options, timeout) {
    return new Promise((resolve, reject) => {
      fetch(url, options).then(resolve, reject);

      if (timeout) {
        const e = new Error("Connection timed out");
        setTimeout(reject, timeout, e);
      }
    });
  }

如果您没有在代码中配置超时,它将是浏览器的默认请求超时。

1) Firefox - 90秒

在Firefox URL字段中输入about:config。找到key network.http.connection-timeout对应的值

2) Chrome - 300秒

一个更简单的方法是在MDN中:https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal#aborting_a_fetch_operation_with_a_timeout

try {
    await fetch(url, { signal: AbortSignal.timeout(5000) });
} catch (e) {
    if (e.name === "TimeoutError") {
        console.log('5000 ms timeout');
    }
}