Javascript:重复调用 promises 直到返回所需的结果并在之后触发事件?

Gen*_*ias 1 javascript node.js promise ecmascript-6

我目前有这个问题,我在 JavaScript 中调用 API 来返回已提交作业的状态。作业状态可以是“QUEUED”、“RUNNING”或“COMPLETED”。我以承诺的形式收到此 API 调用的结果。我有一个名为 pollJob 的函数,它进行 API 调用并返回一个承诺,该承诺最终解决并让我知道工作是否完成。我的问题是,我必须反复调用 pollJob,直到我得到一个解析为“已完成”的作业状态,然后发出某种通知以触发前端的某种操作,从而发生。

这是到目前为止我一直在尝试做的一个例子,但它不起作用,因为 Javascript 没有延迟函数的概念,每次超时都不会阻塞而是触发,让代码继续,然后触发一旦分配的时间过去,就包含代码。我正在使用 setTimeout 并在每个循环中乘以延迟以在交错实例中进行调用,基本上是分散每个 API 调用,因为作业完成可能需要长达一分钟的时间:

  var res = "";
  var i = 0;
  var delay = 1000;
  while (!api.isJobDone(res) && i < 15) {
    setTimeout(function() {
      api.pollJob()
      .then(function(status) {
        console.log("STATUS IN LOOPUNTILDONE: " + status);  
        (res = status)
        if (api.isJobDone(status)) {
          // let the front end know the job is complete
        }
      });
    }, delay);
    delay *= 3;
    i++;
  }
  return res;
Run Code Online (Sandbox Code Playgroud)

我在以异步方式考虑此代码时遇到了很多麻烦,并且很难考虑如何在循环中调用此承诺,直到它给我所需的结果,然后将该信息发送到前端让那部分代码知道继续。有没有更聪明的方法来设计这个?非常感谢任何建议或提示。谢谢!

Mar*_*yer 5

如果您使用的是 Node 8,您可以使用async/awaitwhich 让您以一种非常易读的方式编写它。

// a delay function
function wait(delay){
    return new Promise(resolve => setTimeout(resolve, delay))
}

// poll in while loop until conditions are met
async function poll(){
    let res
    let i = 0
    const DELAY = 1000
    while (!api.isJobDone(res) && i < 15){
        res = await api.pollJob()
        console.log("STATUS IN LOOPUNTILDONE: " + res); 
        if (api.isJobDone(res)) {
            console.log("done")
        }
        await wait(DELAY)   
        i++     
    }
}
// make it so
poll()
Run Code Online (Sandbox Code Playgroud)

这是一个api应该在现代浏览器中运行的模拟片段:

// a delay function
function wait(delay){
    return new Promise(resolve => setTimeout(resolve, delay))
}

// poll in while loop until conditions are met
async function poll(){
    let res
    let i = 0
    const DELAY = 1000
    while (!api.isJobDone(res) && i < 15){
        res = await api.pollJob()
        console.log("STATUS IN LOOPUNTILDONE: " + res); 
        if (api.isJobDone(res)) {
            console.log("done")
        }
        await wait(DELAY)   
        i++     
    }
}
// make it so
poll()
Run Code Online (Sandbox Code Playgroud)