我对以下简单的Promise示例感到困惑。
问题1:从控制台日志中,为什么在console.log(" 200")语句之后执行解析?
问题2:在onload()之前启用resolve()并使用无效的url发出GET请求。即使AJAX返回404,这次拒绝也不会被调用,因为onload之前的解析被调用了。为什么不被拒绝被召唤?
https://jsfiddle.net/tut5va0m/3/
function get(url) {
// Return a new promise.
return new Promise(function(resolve, reject) {
// Do the usual XHR stuff
var req = new XMLHttpRequest();
req.open('GET', url);
//Enable below for Question 2
//resolve(req.response);
req.onload = function() {
// This is called even on 404 etc
// so check the status
if (req.status == 200) {
//Question 1
resolve(req.response);
console.log("200");
}
else {
// Otherwise reject with the status text
// which will hopefully be a meaningful error
reject(Error(req.statusText));
}
};
// Handle network errors
req.onerror = function() {
reject(Error("Network Error"));
};
// Make the request
req.send();
});
}
function resolve(data) {
console.log("Success!!! " + data);
}
function reject(data) {
console.log("Fail!!! " + data);
}
var url = '/echo/json';
var invalidUrl = '/abc'
get(url).then(resolve, reject);
//below is for Question 2
get(invalidUrl).then(resolve, reject);
答案 0 :(得分:2)
对于问题A,请解决使用process.nextTick(), 因此,在调用resolve回调之前,当前函数可能会完成。 这就是你在“成功”之前看到“200”的原因
对于问题B,无法解决和拒绝承诺。 您必须选择或操作成功并解决或失败并被拒绝。它可以是两者。
答案 1 :(得分:1)
Promise通常用于异步操作,因此遵循promise操作的行(例如.then
)将在执行promise处理程序之前执行。如果您使用回调函数(例如包含在req.onload
函数中的代码),这种行为对您来说应该很熟悉。使用您的代码,您所看到的是Promise.resolve
正在执行,然后是console.log
,然后是任何链接到Promise的内容,在您的情况下,其中包含令人困惑的名称resolve
和{{ 1}}在此行注册:
reject
更清楚的是重命名那些函数 afterResolve 和 afterReject ,因为那些函数执行时就是这样。如果你想确保在解析或拒绝promise之后执行get(url).then(resolve, reject);
,你需要将那个语句放在那些promise-handling函数中,或者链接另一个函数并在那里执行。
console.log
关于你的第二个问题,只有一次才能解决或拒绝承诺。您无法多次解决此问题,也无法在问题解决后拒绝。这个承诺在它被解决或拒绝之后就已经完成了它的职责,并且这些功能在之后不会做任何事情。在那之后你需要创造新的承诺。
get(url).then(resolve, reject).then(function(){
console.log('It worked')
})