我对使用bluebird的承诺很陌生。当状态响应从api更改为"成功"时,我试图解决一个承诺。下面是我的代码:
exports.getdata(taskCreation, headers) {
var deferred = Promise.pending();
var headers = {
"Authorization": "Secret xxxxxxxxxxxxxxxxx"
};
while (true) {
request.get({
url: "https://dragon.stupeflix.com/v2/status",
qs: {
tasks: taskCreation[0]["key"]
},
headers: headers,
json: true
}, function (error, httpObj, taskStatusAndResult) {
if (!error && httpObj.statusCode == 200) {
console.log(taskStatusAndResult[0]["status"]); //contains either "queued", "executing", "success", or "error"
if (taskStatusAndResult[0]["status"] == "success")
deferred.resolve(taskStatusAndResult);
} else {
deferred.reject(error);
}
})
}
return deferred.promise;
}
api需要几秒钟来处理视频,生成videourl并显示"成功"状态。在此之前,我想反复调用api,并解决承诺只有当状态是"成功"。我的代码与无限while循环不工作。关于如何以最好的方式实现这一要求,有什么建议吗?
您应该始终在尽可能低的级别承诺,以便您可以对其他所有内容使用承诺。
function makeRequest() {
return new Promise(function(resolve, reject) {
request.get({
url: "https://dragon.stupeflix.com/v2/status",
qs: {
tasks: taskCreation[0]["key"]
},
headers: {
"Authorization": "Secret xxxxxxxxxxxxxxxxx"
},
json: true
}, function (error, httpObj, taskStatusAndResult) {
if (error) reject(error);
else if (httpObj.statusCode != 200) reject(httpObj); // or so
else resolve(taskStatusAndResult);
});
});
}
现在我们可以使用承诺语法来编码你的应用程序用例,在这种情况下,一个递归算法,重新尝试请求,直到它得到一个success
:
function getData(taskCreation, headers) {
return makeRequest(taskCreation, headers).then(function(taskStatusAndResult) {
if (taskStatusAndResult[0]["status"] == "success")
return taskStatusAndResult;
else
return getData(taskCreation, headers); // do it again
});
}
exports.getdata = getData;
不能在异步操作中使用while()
循环。它会在任何一个API调用完成之前启动无数个API调用。相反,你必须对事情进行排序。进行一次API调用。得到结果后,在结果处理程序中决定下一步要做什么。
另外,您没有对您创建的承诺做任何事情,所以我决定从您的函数返回承诺。
并且,你的exports.getData
声明不是一个正确的函数声明。
这里有一个想法,你返回一个承诺,如果你最终找到"成功"状态,承诺将被解决,如果出现错误条件,承诺将被拒绝。
实现以下逻辑:
- 调用API。当你得到响应时,做以下四件事之一:
- 如果响应是错误的,用该错误拒绝承诺
- 如果响应成功,用结果 解析承诺
- 如果响应不是错误,但尚未成功,并且您已超过重试的最大次数,则使用最大重试次数拒绝
- 如果响应不是错误,但还没有成功,并且没有超过重试的最大次数,那么再试一次
- 从函数返回一个承诺,这样调用者就可以在承诺上使用
.then()
来从操作中获得结果或错误
代码如下:
exports.getdata = function (taskCreation, headers) {
var headers = {"Authorization": "Secret xxxxxxxxxxxxxxxxx"};
var cntr = 0;
var maxRetries = 20;
return new Promise(function (resolve, reject) {
function next() {
++cntr;
request.get({
url: "https://dragon.stupeflix.com/v2/status",
qs: {tasks: taskCreation[0]["key"]},
headers: headers,
json: true
}, function (error, httpObj, taskStatusAndResult) {
if (!error && httpObj.statusCode == 200) {
console.log(taskStatusAndResult[0]["status"]); //contains either "queued", "executing", "success", or "error"
if (taskStatusAndResult[0]["status"] === "success") {
// found success to resolve the promise
resolve(taskStatusAndResult);
} else {
// if not "success" yet, then try again
if (cntr > maxRetries) {
reject(new Error("max retries exceeded"));
} else {
// try again
next();
}
}
} else {
// got some kind of error here, so stop further processing
reject(error);
}
})
}
// start the first request
next();
});
}