Promise 状态及结构

ES6 规定,Promise对象是一个构造函数,用来生成Promise实例

 下面是创建一个Promise实例

  const promise = new Promise(function(resolve, reject) {

     if(/*异步操作成功*/){
         resolve(value)
     }
     else{
         reject(error)
     }
  })

Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject. 它们是两个函数,由javascript引擎提供、

resolve 函数的作用是,将Promise对象的状态从“未完成”变为“成功”,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;

reject 函数的作用是,将promise对象的状态从“未完成”变为"失败",在异步操作失败时调用。

 Promise实例生成后,可以用then方法指定resolved状态和rejected状态的回调函数,

   promise.then( function(value){
      // success
   }, function(error){
      // failure
   });

 promise对象的简单的例子

function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'done');
  });
}

timeout(100).then((value) => {
  console.log(value);
});

     上边代码中,timeout方法返回一个promise实例,表示一段时间后才会发生的结果,过了指定的时间(ms参数)以后,Promise实例的状态改变为resolved,就会触发then方法绑定的回调函数

 promise新建后就会立即执行

let promise = new Promise(function(resolve, reject) {
  console.log('Promise');
  resolve();
});

promise.then(function() {
  console.log('resolved.');
});

console.log('Hi!');

// Promise
// Hi!
// resolved

     上面代码中,Promise新建后立即执行,所以首先输出的Promise。然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以resolved最后输出。

 下面是异步加载图片的例子

function loadImageAsync(url) {
  return new Promise(function(resolve, reject) {
    const image = new Image();

    image.onload = function() {
      resolve(image);
    };

    image.onerror = function() {
      reject(new Error('Could not load image at ' + url));
    };

    image.src = url;
  });
}

 下面是Ajax操作的例子

const getJSON = function(url) {
  const promise = new Promise(function(resolve, reject){
    const handler = function() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
    const client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

  });

  return promise;
};

getJSON("/posts.json").then(function(json) {
  console.log('Contents: ' + json);
}, function(error) {
  console.error('出错了', error);
});

 上边的代码中,getJSON是对XMLHttpRequest对象的封装

    如果调用resolve函数和reject函数时带有参数,那么它们的参数会被传递给回调函数,reject函数的参数通常是  Error对象的实例,表示抛出的错误;resolve函数的参数除了正常的值以外,还可能是另一个Promise实例

  比如下面这样,

const p1 = new Promise(function (resolve, reject) {
  // ...
});

const p2 = new Promise(function (resolve, reject) {
  // ...
  resolve(p1);
})

 上边代码中,p1 和 p2都是Promise的实例,但是p2的resolve方法将p1作为参数,即一个异步操作的结果是返回另一个异步操作结果。

  注意,这时p1的状态就会传递给p2,也就是说,p1的状态决定了p2的状态,如果p1的状态是pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是resolved或者rejected,那么p2的回调函数就会立即执行。

const p1 = new Promise(function (resolve, reject) {
  setTimeout(() => reject(new Error('fail')), 3000)
})

const p2 = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(p1), 1000)
})

p2
  .then(result => console.log(result))
  .catch(error => console.log(error))
// Error: fail

    上面代码中,p1是一个Promise,3秒之后变为rejected。p2的状态在1s之后发生改变,resolve方法返回的是p1。由于p2返回的是另一个Promise,导致p2自己的状态无效了,由p1的状态决定p2的状态,所以,后面的then语句都变成了针对后者p1

注意,调用resolve或reject并不会终结Promise的参数函数的执行,

new Promise((resolve, reject) => {
  resolve(1);
  console.log(2);
}).then(r => {
  console.log(r);
});
// 2
// 1

   上面代码中,调用resolve(1)以后,后面的console.log(2)还是会执行,并且会首先打印出来。这是因为立即 resolved 的 Promise 是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。

    一般来说,调用resolvereject以后,Promise 的使命就完成了,后继操作应该放到then方法里面,而不应该直接写在resolvereject的后面。所以,最好在它们前面加上return语句,这样就不会有意外。

new Promise((resolve, reject) => {
  return resolve(1);
  // 后面的语句不会执行
  console.log(2);
})
未完,待续......
原文地址:https://www.cnblogs.com/zhishiyv/p/13813040.html