我有一个fetch-api POST请求:

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

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


当前回答

编辑1

正如注释中所指出的,原始答案中的代码即使在承诺被解析/拒绝之后也会继续运行计时器。

下面的代码修复了这个问题。

function timeout(ms, promise) {
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      reject(new Error('TIMEOUT'))
    }, ms)

    promise
      .then(value => {
        clearTimeout(timer)
        resolve(value)
      })
      .catch(reason => {
        clearTimeout(timer)
        reject(reason)
      })
  })
}


原来的答案

它没有指定的默认值;该规范根本没有讨论超时。

你可以为promise实现自己的超时包装器:

// Rough implementation. Untested.
function timeout(ms, promise) {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      reject(new Error("timeout"))
    }, ms)
    promise.then(resolve, reject)
  })
}

timeout(1000, fetch('/hello')).then(function(response) {
  // process response
}).catch(function(error) {
  // might be a timeout error
})

如https://github.com/github/fetch/issues/175所述 评论来源:https://github.com/mislav

其他回答

编辑1

正如注释中所指出的,原始答案中的代码即使在承诺被解析/拒绝之后也会继续运行计时器。

下面的代码修复了这个问题。

function timeout(ms, promise) {
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      reject(new Error('TIMEOUT'))
    }, ms)

    promise
      .then(value => {
        clearTimeout(timer)
        resolve(value)
      })
      .catch(reason => {
        clearTimeout(timer)
        reject(reason)
      })
  })
}


原来的答案

它没有指定的默认值;该规范根本没有讨论超时。

你可以为promise实现自己的超时包装器:

// Rough implementation. Untested.
function timeout(ms, promise) {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      reject(new Error("timeout"))
    }, ms)
    promise.then(resolve, reject)
  })
}

timeout(1000, fetch('/hello')).then(function(response) {
  // process response
}).catch(function(error) {
  // might be a timeout error
})

如https://github.com/github/fetch/issues/175所述 评论来源:https://github.com/mislav

下面是一个使用NodeJS的SSCCE,它将在1000ms后超时:

import fetch from 'node-fetch';

const controller = new AbortController();
const timeout = setTimeout(() => {
    controller.abort();
}, 1000); // will time out after 1000ms

fetch('https://www.yourexample.com', {
    signal: controller.signal,
    method: 'POST',
    body: formData,
    credentials: 'include'
}
)
.then(response => response.json())
.then(json => console.log(json))
.catch(err => {
    if(err.name === 'AbortError') {
        console.log('Timed out');
    }}
)
.finally( () => {
    clearTimeout(timeout);
});

您可以创建一个timeoutPromise包装器

function timeoutPromise(timeout, err, promise) {
  return new Promise(function(resolve,reject) {
    promise.then(resolve,reject);
    setTimeout(reject.bind(null,err), timeout);
  });
}

然后可以包装任何承诺

timeoutPromise(100, new Error('Timed Out!'), fetch(...))
  .then(...)
  .catch(...)  

它实际上不会取消底层连接,但允许您超时承诺。 参考

使用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.
    });
  fetchTimeout (url,options,timeout=3000) {
    return new Promise( (resolve, reject) => {
      fetch(url, options)
      .then(resolve,reject)
      setTimeout(reject,timeout);
    })
  }