web-dev-qa-db-fra.com

Récupérer le délai d'expiration de la demande d'API?

J'ai une demande fetch-apiPOST

   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 lui attribuer une valeur particulière telle que 3 secondes ou des secondes indéfinies?

38
Akshay Lokur

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

Vous pouvez implémenter votre propre wrapper timeout 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

40
shakeel

J'aime vraiment l'approche propre de cette Gist using 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

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

En utilisant la syntaxe d'abandon, 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);


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

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

Voir AbortController page sur MDN.

17
Endless

il n'y a pas encore de prise en charge de délai d'attente dans l'API d'extraction. 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
code-jaff

EDIT: la demande d'extraction sera toujours exécutée en arrière-plan et enregistrera probablement une erreur dans votre console. 

En effet, l’approche Promise.race est meilleure.

Voir ce lien pour référence Promise.race ()

Course signifie que toutes les promesses seront exécutées en même temps et la course s'arrêtera dès qu'une des promesses retournera une valeur . Par conséquent, une seule valeur sera renvoyée . passe une fonction à appeler si le délai de récupération est dépassé.

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
Arroganz

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(...)  

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

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