我目前有这个问题,我在javascript中调用API来返回已提交作业的状态。工作状态可以是“QUEUED”,“RUNNING”或“COMPLETED”。我以promise的形式收到此API调用的结果。我有一个名为pollJob的函数,它进行API调用并返回一个最终解析的promise,让我知道作业是否完成。我的问题是,我必须多次调用pollJob,直到我得到一个解析为'COMPLETED'的作业状态,然后发出某种通知,以便在前端触发某种操作,从而导致结果发生。
这是我到目前为止尝试做的一个例子,但它不起作用,因为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;
我在以异步方式思考这段代码时遇到了很多麻烦,并且很难思考如何在循环中调用此承诺,直到它给出了我想要的结果,然后将该信息发送给前端让代码的那部分知道继续。有没有更聪明的方法来设计它?任何建议或提示都非常感谢。谢谢!
答案 0 :(得分:3)
如果您使用的是Node 8,则可以使用async/await
,以便以可读的方式编写它。
// 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()
这是一个带有模拟api
的片段,应该在现代浏览器中运行:
// mock api
var api = {
pollJob: function() {
return new Promise((resolve) => {
setTimeout(() => resolve(Math.random()), 500)
})
},
isJobDone: function(status) {
return status < 0.3
}
}
function wait(delay) {
return new Promise(resolve => setTimeout(resolve, delay))
}
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++
}
}
poll()
&#13;
答案 1 :(得分:1)
这可能更适合递归,而不是使用while
循环:
function checkIfJobIsDone() {
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
} else {
checkIfJobIsDone();
}
});
}
这样,在上一个API返回之前,它不会再进行另一个API调用