【问题标题】:Javascript: how to create an infinite-loop of promises?Javascript:如何创建一个无限循环的承诺?
【发布时间】:2020-09-24 01:02:51
【问题描述】:

我想用Javascript编写以下伪代码:

function asyncOperation() {
   return new Promise((resolve, reject) => {
      ....
   }
}

while (true) { 
    result = asyncOperation()
    if result is good then break the loop;
    else loop again
}

我会用文字来解释:asyncOperation 使用 Promise,例如 AJAX 调用。我希望如果 promise 被拒绝,那么 asyncOperation 将再次被调用。你知道如何用 Javascript 来实现吗?

【问题讨论】:

  • 您在支持异步/等待的平台上吗?我觉得使用带有标志的 while 和相应地设置此标志的 try/catch 会非常简单。
  • async/await 是 Promises 的语法糖。
  • 可以,但不是所有平台都支持。
  • 答案很简单:您有绝对没有种方法可以做到这一点,而不会使您的调用代码异步。

标签: javascript promise es6-promise


【解决方案1】:

如果您要使用循环,则必须使用await,否则,您的循环将永远运行,并且永远不会给异步操作任何周期来实际处理其完成:

while (true) { 
    result = await asyncOperation()
    if (good result) {
         break;
    }
}

当然,这需要在声明为 async 的函数中。


await 之前,执行此操作的通常方法是使用本地函数和递归外观结构(顺便说一下,由于异步操作,递归不会产生任何堆栈):

function run() {
    return asyncOperation().then(result => {
        if (good result) {
            return result;
        } else {
            // try again
            return run();
        }
    });
}

run().then(result => {
   console.log(result);
}).catch(err => {
   console.log(err);
});

而且,通常您会在再次调用asyncOperation() 之前插入一些小的延迟,以避免重击目标服务器。而且,您将有一个超时或最大重试次数,以避免此循环永远运行的情况。

【讨论】:

  • 这绝对是一个有效的答案,但正如您所知,递归可能效率很低。没有递归有什么选择吗?
  • @CrazySynthax - 由于这里的异步性质,它并不是真正的递归。在调用 .then() 处理程序之前堆栈完全展开,因此没有堆栈堆积。而且,为什么不直接使用更简单的await 选项。
【解决方案2】:

这样的事情还不够吗:

async function loopUntilTrue() {
  let success = false;

  while (!success) {
    try {
      await asyncOperation();
      success = true;
    } catch {
      success = false;
    }
  }
}

【讨论】:

  • while(!(await asyncOperation());的路很长
【解决方案3】:

我为此创建了一个循环函数

let count = 0;
function asyncOperation() {
  return new Promise((resolve, reject) => {
    if (count < 10) {
      console.log('reject', count++);
      reject();
      return;
    }
    resolve(console.log('resolve', count));
  });
}

async function loop() {
  while (true) {
    try {
      await asyncOperation();

      break;
    } catch {
      continue;
    }
  }
}

loop();

结果是这样的:

reject 0
reject 1
reject 2
reject 3
reject 4
reject 5
reject 6
reject 7
reject 8
reject 9
resolve 10

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-24
    • 2018-03-13
    • 2015-12-18
    • 2016-11-08
    • 1970-01-01
    • 2019-12-07
    • 1970-01-01
    相关资源
    最近更新 更多