Fetch API délai d'attente de la demande?

J'ai un fetch-api POST demande:

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

Je veux savoir quel est le délai d'attente par défaut pour cela? et comment pouvons-nous fixer à une valeur particulière comme 3 secondes ou indéterminée secondes?

23
demandé sur Akshay Lokur 2017-10-26 08:23:17

6 réponses

Il n'a pas de valeur par défaut spécifiée; la spécification ne traite pas du tout des délais d'attente.

Vous pouvez implémenter votre propre wrapper de délai d'attente pour les promesses en général:

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

Comme décrit dans https://github.com/github/fetch/issues/175 Commentaire de https://github.com/mislav

24
répondu shakeel 2018-06-15 08:49:17

J'aime vraiment l'approche propre de cettegist en utilisant Promise.course

va chercher le temps mort.js

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

principal.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
})
25
répondu Karl Adler 2018-05-02 06:57:05

Il n'y a pas encore de prise en charge du délai d'attente dans l'API fetch. Mais cela pourrait être réalisé en l'enveloppant dans une promesse.

Pour par exemple.

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

      if (timeout) {
        const e = new Error("Connection timed out");
        setTimeout(reject, timeout, e);
      }
    });
  }
4
répondu code-jaff 2017-10-26 05:39:27

En utilisant la syntaxe abort, vous pourrez faire:

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

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

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

Si vous vouliez seulement temporiser la requête, pas la réponse, ajoutez:

clearTimeout(timeoutId);
// …
3
répondu Endless 2018-04-30 12:55:26

EDIT : la requête fetch sera toujours en cours d'exécution en arrière-plan et enregistrera probablement une erreur dans votre console.

En effet la promesse.la course approche est la meilleure.

Voir ce lien pour référence Promesse.course()

Course signifie que toutes les Promesses d'exécuter en même temps, et la course s'arrêtera dès que l'une des promesses renvoie une valeur. Par conséquent, seule valeur sera retournée. Vous pouvez également passer une fonction à appeler si le fetch fois sur.

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

Si cela vous intéresse, une implémentation possible serait:

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;
   }
}
1
répondu Arroganz 2018-05-02 08:58:03

Vous pouvez créer un wrapper timeoutPromise

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

Vous pouvez ensuite envelopper toute promesse

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

Il n'annulera pas réellement une connexion sous-jacente mais vous permettra de temporiser une promesse.
Référence

0
répondu Pulkit Aggarwal 2018-07-27 06:17:38