仅当功能运行10次时才进行下一步

时间:2016-10-05 14:53:39

标签: javascript typescript promise rxjs

我有这个功能:

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);
                  });

我觉得我这样做的方式很丑陋,可以做到更好。有什么建议吗?

3 个答案:

答案 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很难。

setIntervalsetTimeout API本身具有可怕的错误处理特性,并且最好包含在微小的承诺返回函数中,永远不会再被直接调用。

请注意,对于repetitions的高值,这不是特别有效。