JavaScript Promise解析并拒绝函数调用序列

时间:2016-04-20 14:14:53

标签: javascript promise

我对以下简单的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);

2 个答案:

答案 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')
})