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

JavaScript Promise resolve and reject function call sequence

本文关键字:函数调用 拒绝 Promise JavaScript      更新时间:2023-09-26

我对下面的简单承诺示例感到困惑。

问题 1:从控制台日志中,为什么在控制台.log("200") 语句之后执行解析?

问题 2:在 onload() 之前启用 resolve(),并使用无效的 url 发出 GET 请求。即使 AJAX 返回了 404,这次也不会调用拒绝,因为调用了加载前的解析。为什么拒绝不会被称为?

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);

承诺通常用于异步操作,因此在执行承诺处理程序之前,将在承诺操作(例如 .then)后面执行一行。如果您习惯于回调函数(例如包装在 req.onload 函数中的代码),则您应该熟悉此行为。使用您的代码,您看到的是执行Promise.resolve,然后是console.log,然后是链接到 Promise 的任何内容,在您的情况下,这些名称resolvereject令人困惑,如在此行中注册:

get(url).then(resolve, reject);

Resolve 和 afterReject 之后重命名这些函数会更清楚,因为那是这些函数执行的时候。如果你想确保在解决或拒绝承诺后执行console.log,你需要将该语句放在那些承诺处理函数中,或者链接另一个函数并在那里执行。

get(url).then(resolve, reject).then(function(){
    console.log('It worked')
})

至于你的第二个问题,一个承诺只能解决或拒绝一次。您不能多次解决它,也不能在解决后拒绝它。该承诺在解决或拒绝后已经完成了它的职责,调用这些函数之后不会做任何事情。在那之后,你需要创建新的承诺。

get(url).then(function successFirstRequest(){
    return get(someOtherUrl)
}).then(function successSecondRequest(){
   alert('Completed two network requests')
}).catch(err){
   // one of your requests failed
})

对于问题 A,请解决 use process.nextTick(),因此,当前函数可能会在调用解析回调之前完成。这就是为什么你在"成功"之前看到"200"的原因

对于问题 B,承诺不能既解决又被拒绝。您必须选择或操作成功并已解决,或者操作失败并被拒绝。可以两者兼而有之。