Edit
delay
and maxRetries
).delay
and maxRetries
).delay
provided).Code for #1. Keeps on retrying until promise resolves (any improvements community for the language etc?)
Promise.retry = function(fn, times, delay) { return new Promise(function(resolve, reject){ var error; var attempt = function() { if (times == 0) { reject(error); } else { fn().then(resolve) .catch(function(e){ times--; error = e; setTimeout(function(){attempt()}, delay); }); } }; attempt(); }); };
Use
work.getStatus() .then(function(result){ //retry, some glitch in the system return Promise.retry(work.unpublish.bind(work, result), 10, 2000); }) .then(function(){console.log('done')}) .catch(console.error);
Code for #2 keep on retrying until a condition meets on the then
result in a reusable way (condition is what will vary).
work.publish() .then(function(result){ return new Promise(function(resolve, reject){ var intervalId = setInterval(function(){ work.requestStatus(result).then(function(result2){ switch(result2.status) { case "progress": break; //do nothing case "success": clearInterval(intervalId); resolve(result2); break; case "failure": clearInterval(intervalId); reject(result2); break; } }).catch(function(error){clearInterval(intervalId); reject(error)}); }, 1000); }); }) .then(function(){console.log('done')}) .catch(console.error);
To retry the promise we have to call the same function recursively with reduced max tries, if the promise failed that is in the catch block. Check if there is a number of tries left then recursively call the same function or else reject with the final error.
A promise is just an object with properties in Javascript. There's no magic to it. So failing to resolve or reject a promise just fails to ever change the state from "pending" to anything else. This doesn't cause any fundamental problem in Javascript because a promise is just a regular Javascript object.
The Promise. resolve() method "resolves" a given value to a Promise . If the value is a promise, that promise is returned; if the value is a thenable, Promise. resolve() will call the then() method with two callbacks it prepared; otherwise the returned promise will be fulfilled with the value.
import fetch from 'node-fetch'; let attempts = 0; const wait = (time = 0) => { return new Promise((resolve) => { setTimeout(() => { resolve(); }, time * 1000); }); }; const retryFetch = async (url = '', options = {}) => { const { retry = null, retryDelay = 0, retries = 5, ...
Something a bit different ...
Async retries can be achieved by building a .catch()
chain, as opposed to the more usual .then()
chain.
This approach is :
Otherwise, use a recursive solution.
First, a utility function to be used as a .catch()
callback.
var t = 500; function rejectDelay(reason) { return new Promise(function(resolve, reject) { setTimeout(reject.bind(null, reason), t); }); }
Now you can build .catch chains very concisely :
1. Retry until the promise resolves, with delay
var max = 5; var p = Promise.reject(); for(var i=0; i<max; i++) { p = p.catch(attempt).catch(rejectDelay); } p = p.then(processResult).catch(errorHandler);
DEMO: https://jsfiddle.net/duL0qjqe/
2. Retry until result meets some condition, without delay
var max = 5; var p = Promise.reject(); for(var i=0; i<max; i++) { p = p.catch(attempt).then(test); } p = p.then(processResult).catch(errorHandler);
DEMO: https://jsfiddle.net/duL0qjqe/1/
3. Retry until result meets some condition, with delay
Having got your mind round (1) and (2), a combined test+delay is equally trivial.
var max = 5; var p = Promise.reject(); for(var i=0; i<max; i++) { p = p.catch(attempt).then(test).catch(rejectDelay); // Don't be tempted to simplify this to `p.catch(attempt).then(test, rejectDelay)`. Test failures would not be caught. } p = p.then(processResult).catch(errorHandler);
test()
can be synchronous or asynchronous.
It would also be trivial to add further tests. Simply sandwich a chain of thens between the two catches.
p = p.catch(attempt).then(test1).then(test2).then(test3).catch(rejectDelay);
DEMO: https://jsfiddle.net/duL0qjqe/3/
All versions are designed for attempt
to be a promise-returning async function. It could also conceivably return a value, in which case the chain would follow its success path to the next/terminal .then()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With