web-dev-qa-db-ja.com

APIリクエストのタイムアウトを取得しますか?

fetch-apiPOSTリクエストがあります。

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

私はこれのためのデフォルトのタイムアウトが何であるか知りたいですか? 3秒や無期限のような特定の値に設定するにはどうすればよいでしょうか。

50
Akshay Lokur

指定されたデフォルトはありません。 仕様 タイムアウトについてはまったく議論されていません。

一般的に約束のためにあなた自身のタイムアウトラッパーを実装することができます。

// 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

49
Bruce Lee

私はこれからのきれいなアプローチがとても好きです 要旨 using Promise.race

Timeout.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

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

中止構文を使用すると、以下のことが可能になります。

const controller = new AbortController();
const signal = controller.signal;

const fetchPromise = fetch(url, {signal});

// 5 second timeout:
const timeoutId = setTimeout(() => controller.abort(), 5000);


fetchPromise.then(response => {
  // completed request before timeout fired

  // If you only wanted to timeout the request, not the response, add:
  // clearTimeout(timeoutId);
})

MDNの AbortController ページを参照してください。

26
Endless

フェッチ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);
      }
    });
  }
4
code-jaff

EDIT:フェッチ要求はまだバックグラウンドで実行されており、おそらくコンソールにエラーを記録します。

確かに、Promise.raceのアプローチが優れています。

参照用にこのリンクを参照してください Promise.race()

競合とは、すべての約束が同時に実行されることを意味し、いずれかの約束が値を返すとすぐにレースが停止します。したがって、は1つの値のみが返されます。フェッチがタイムアウトした場合に呼び出す関数を渡すこともできます。

fetchWithTimeout(url, {
  method: 'POST',
  body: formData,
  credentials: 'include',
}, 5000, () => { /* do stuff here */ });

これがあなたの興味を覗くならば、考えられる実装は次のようになります。

function fetchWithTimeout(url, options, delay, onTimeout) {
   const timer = new Promise((resolve) => {
      setTimeout(resolve, delay, {
      timeout: true,
     });
   });
   return Promise.race([
      fetch(path, request),
      timer
   ]).then(response) {
      if (response.timeout) { 
        onTimeout();
      }
      return response;
   }
}
2
Arroganz

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!'), fetcn(...))
  .then(...)
  .catch(...)  

基になる接続を実際にキャンセルすることはありませんが、約束をタイムアウトにすることができます。
参考

0
Pulkit Aggarwal
  fetchTimeout (url,options,timeout=3000) {
    return new Promise( (resolve, reject) => {
      fetch(url, options)
      .then(resolve,reject)
      setTimeout(reject,timeout);
    })
  }
0
Mojimi