Repeat a Promise until it's not rejected or reach a timeout
As Mike McCaughan mentioned, you can use setTimeout
to create a delay between attempts. Resolve or reject your promise once it succeeds or you run out of attempts.
function createPromise(tries, willFail) {
return new Promise(function cb(resolve, reject) {
console.log(tries + ' remaining');
if (--tries > 0) {
setTimeout(function() {
cb(resolve, reject);
}, 500);
} else {
if (willFail) {
reject('Failure');
} else {
resolve('Success');
}
}
});
}
// This one will fail after 3 attempts
createPromise(3, true)
.then(msg => console.log('should not run'))
.catch(msg => {
console.log(msg);
// This one will succeed after 5 attempts
return createPromise(5, false);
})
.then(msg => console.log(msg))
.catch(msg => console.log('should not run'));
tdc
Updated on June 19, 2022Comments
-
tdc almost 2 years
I'm still a Promise noob and am trying to figure out how to have my Promise repeat itself.
have an ES6 promise that rejects if some global flag is not set. I need it to retry every 500ms until either:
- the promise returns a resolve,
- or a max number of attempts are reached (lets say 10).
Since Promises are async, I don't really want to use a
setInterval()
check, because I don't think that'd work correctly with asynchronous code. I need the checking to terminate as soon as the promise is resolved successfully ( or timeout reached ).I'm using ES6 + React + ES6 Promises (so no Q or Bluebird-specific answers, please!)
http://jsfiddle.net/2k2kz9r9/8/
// CLASS class Test extends React.Component { constructor() { this.state = { status: 'setting up..', } } componentDidMount() { // TODO: how do I get this to loop with a timeout? this.createSlot() .then((slot) => { this.setState({ status: slot }); }) .catch((e) => { this.setState({ status: e.message }); }) } createSlot() { return new Promise((resolve, reject) => { if (!this.checkIsReady()) { reject(new Error('Global isnt ready yet')); } // more stuff here but going to resolve a string for simplicity sake resolve('successful!'); }); } checkIsReady() { return window.globalThing && window.globalThing === true; } render() { return ( <div>{this.state.status}</div> ); } } // RENDER OUT React.render(< Test/> , document.getElementById('container'));
EDIT: function based on current feedback:
createSlot(tries) { const _this = this; return new Promise(function cb(resolve, reject) { console.log(`${tries} remaining`); if (--tries > 0) { setTimeout(() => { cb(resolve, reject); }, 500); } else { const { divId, adUnitPath } = _this; const { sizes } = _this.props; // if it's not, reject if (!_this.isPubadsReady()) { reject(new Error('pubads not ready')); } // if it's there resolve window.googletag.cmd.push(() => { const slot = window.googletag .defineSlot(adUnitPath, sizes, divId) .addService(window.googletag.pubads()); resolve(slot); }); } }); }