我有这个功能:
function setIntervalX(callback, delay, repetitions): Promise<any> {
let promises = [];
var x = 0;
var intervalID = window.setInterval(function () {
callback();
if (++x === repetitions) {
window.clearInterval(intervalID);
promises.push(new Promise((resolve, reject) => {});
}
}, delay);
return Promise.all(promises);
}
我的目标是在测试中调用一个函数,在这10个调用结束后,我想在我的函数中调用expect。所以这意味着我必须等待它结束,如下:
setIntervalX(() => {
//logic here
}, 1000, 10).then(() => {
expect(something).toBe(anotherThing);
});
我觉得我这样做的方式很丑陋,可以做到更好。有什么建议吗?
答案 0 :(得分:2)
除非您需要个人承诺(除了Promise.all
之外,您从不使用上述承诺),只需使用一个承诺:
function setIntervalX(callback, delay, repetitions): Promise<any> {
return new Promise(resolve => {
let x = 0;
let intervalID = window.setInterval(function () {
callback();
if (++x === repetitions) {
window.clearInterval(intervalID);
resolve();
}
}, delay);
});
}
答案 1 :(得分:1)
你也标记了RxJS,所以我会抛出一个Rx解决方案。
function setIntervalX(callback, delay, repetitions): Observable<any> {
//Emit an event every delay
return Rx.Observable.interval(delay)
//Only accept a certain number of events
.take(repetitions)
// Process the callback each time
.do(() => callback())
// Convert the result into a promise
.toPromise();
}
setIntervalX(() => {
//logic here
}, 1000, 10)
.then(() => {
expect(something).toBe(anotherThing);
});
答案 2 :(得分:1)
你想要一个更优雅的解决方案,这是怎么回事:
var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
let setIntervalX = (cb, delay, reps) =>
Promise.all(Array(reps).fill().map((n, i) => wait(delay * (i + 1)).then(cb)));
// Demo:
let test = () => Promise.resolve().then(() => (console.log("test"), "!"));
setIntervalX(test, 1000, 10).then(results => console.log(results.join("")));
我将您的问题中的代码解释为希望支持承诺返回callback
。这支持了这一点,并且还正确地传播了错误,这对于setInterval
很难。
setInterval
和setTimeout
API本身具有可怕的错误处理特性,并且最好包含在微小的承诺返回函数中,永远不会再被直接调用。
请注意,对于repetitions
的高值,这不是特别有效。