无限期地循环承诺直到拒绝

时间:2016-07-06 11:34:09

标签: javascript loops promise es6-promise

我有一个执行异步工作并返回Promise的函数,我想无限期地执行此函数,直到承诺为reject

如下所示:

doSomethingAsync().
    .then(doSomethingAsync)
    .then(doSomethingAsync)
    .then(doSomethingAsync)
    // ... until rejection

我做了一点CodePen,所以我可以测试潜在的解决方案:http://codepen.io/JesmoDrazik/pen/pbAovZ?editors=0011

我找到了几个可能的答案,但似乎对我的情况没有任何效果。

如果有人有解决方案,我会很高兴,因为我找不到任何东西!

感谢。

3 个答案:

答案 0 :(得分:4)

你可以做到

(function loop(){
     doSomethingAsync().then(loop);
})();

但是看着你的笔,目前还不清楚拒绝的来源。如果要在用户单击按钮时停止重复操作,可以在按钮处理中更改状态,然后执行

(function loop(){
     doSomethingAsync().then(function(){
          if (!stopped) loop();
     });
})();

答案 1 :(得分:1)

对您的codepen

进行了修改
var FAKE_COUNT = 0;

function doSomething() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('doing something async: ' + FAKE_COUNT)
      if (FAKE_COUNT < 10) {
        resolve();
      } else {
        reject();
      }
      FAKE_COUNT ++;
    }, 1000);
  });
}

const button = document.querySelector('.js-button');

button.addEventListener('click', () => {
  // maybe we can do something here ?
})

function test() {
  doSomething().then(test).catch(() => {
    console.log("Rejected")
  });
}

test();

FAKE_COUNT只是成为标志,所以如果你想通过点击而不是计数来停止承诺,你可以把它作为一个bool并在执行异步任务时检查它

答案 2 :(得分:1)

根据您希望逻辑和拒绝发生的位置,但假设您希望promise本身是自执行的(否则异步执行本身可以循环),它可以将自己作为新的承诺返回:

function doSomething() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('doing something async');
        resolve();
    }, 1000);
  }).then(()=>doSomething());
}

对于拒绝部分,最简单的方法是引入一个标志,(虽然这会使承诺略微减少自我包含):

var stop = false;
function doSomething() {
  return new Promise((resolve, reject) => {
    if(stop)
        reject();
    else{
      setTimeout(() => {
        console.log('doing something async');
        resolve(); //(check for stop could be done here as well)
      }, 1000);
    }
  }).then(()=>doSomething());
}

const button = document.querySelector('.js-button');
button.addEventListener('click', () => {
  stop = true;
});

doSomething();