重复 Promise 直到它没有被拒绝或达到超时
Repeat a Promise until it's not rejected or reach a timeout
我仍然是一个 Promise 菜鸟,我正在努力弄清楚如何让我的 Promise 重演。
有一个 ES6 承诺,如果未设置某些全局标志则拒绝。我需要它每 500 毫秒重试一次,直到:
- 承诺returns决心,
- 或达到最大尝试次数(比如说 10)。
由于 Promises 是异步的,我真的不想使用 setInterval()
检查,因为我认为异步代码无法正常工作。我需要在成功解决承诺(或达到超时)后立即终止检查。
我正在使用 ES6 + React + ES6 Promises(所以没有 Q 或 Bluebird 特定的答案,拜托!)
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'));
编辑:基于当前反馈的函数:
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);
});
}
});
}
您可以尝试链接调用,正如 promises 应该的那样,这有点做作,但我希望您明白我的意思:
PS 将全局对象附加到 windows 是一个坏主意,如果可能的话不应该这样做,这只是展示了一个使用您的流程的简单示例...
window.attempts = 0;
window.maxAttempts = 10;
window.globalThing = true;
function 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!');
}).then((pass) => {
return pass;
}, (fail) => {
window.attempts ++;
//If within attempts, try again
if(window.attempts < window.maxAttempts){
//Chain a new promise to resolve with a timeout of 500ms
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 500);
}).then(() => {
//Then try again
return createSlot();
})
}
else {
//else fail out with reason
return fail;
}
});
}
正如 Mike McCaughan 提到的,您可以使用 setTimeout
在尝试之间创建延迟。一旦成功或您 运行 次尝试,就解决或拒绝您的承诺。
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'));
我仍然是一个 Promise 菜鸟,我正在努力弄清楚如何让我的 Promise 重演。
有一个 ES6 承诺,如果未设置某些全局标志则拒绝。我需要它每 500 毫秒重试一次,直到:
- 承诺returns决心,
- 或达到最大尝试次数(比如说 10)。
由于 Promises 是异步的,我真的不想使用 setInterval()
检查,因为我认为异步代码无法正常工作。我需要在成功解决承诺(或达到超时)后立即终止检查。
我正在使用 ES6 + React + ES6 Promises(所以没有 Q 或 Bluebird 特定的答案,拜托!)
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'));
编辑:基于当前反馈的函数:
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);
});
}
});
}
您可以尝试链接调用,正如 promises 应该的那样,这有点做作,但我希望您明白我的意思:
PS 将全局对象附加到 windows 是一个坏主意,如果可能的话不应该这样做,这只是展示了一个使用您的流程的简单示例...
window.attempts = 0;
window.maxAttempts = 10;
window.globalThing = true;
function 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!');
}).then((pass) => {
return pass;
}, (fail) => {
window.attempts ++;
//If within attempts, try again
if(window.attempts < window.maxAttempts){
//Chain a new promise to resolve with a timeout of 500ms
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 500);
}).then(() => {
//Then try again
return createSlot();
})
}
else {
//else fail out with reason
return fail;
}
});
}
正如 Mike McCaughan 提到的,您可以使用 setTimeout
在尝试之间创建延迟。一旦成功或您 运行 次尝试,就解决或拒绝您的承诺。
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'));