Promise

一、Promise及其底层实现

Promise 是一个对象,保存着未来将要结束的事件,它有两个特征:

(1)对象的状态不受外部影响,Promise 对象代表一个异步操作,有三种状态,pending进行中,fulfilled 已成功,rejected 已失败,只有异步操作的结果,才可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,这也就是promise 名字的由来

(2)一旦状态改变,就不会再变,promise 对象状态改变只有两种可能,从pending 改到fulfilled 或者从pending 改到rejected,只要这两种情况发生,状态就凝固了,不会再改变,这个时候就称为定型resolved,

二、Promise的使用

Promise允许我们通过链式调用的方式来解决“回调地狱”的问题,特别是在异步过程中,通过Promise可以保证代码的整洁性和可读性。

创建一个promise实例:

var p = new Promise(function(resolve, reject){
    setTimeout(function(){
       resolve("success")
    },1000);
    console.log("创建一个新的promise");
});
p.then(function(x){
  console.log(x)
})

//输出:
创建一个新的promise
success

上述是一个promise的实例,输出内容为,“创建一个promise”,延迟1000ms后,输出"success".

从上述的例子可以看出,promise方便处理异步操作。此外promise还可以链式的调用:

var p = new Promise(function(resolve, reject){resolve()});
p.then(...).then(...).then(...)

此外Promise除了then方法外,还提供了Promise.resolve、Promise.all、Promise.race等等方法。

三、Promise/A+规范

①一个promise必须有3个状态,pending,fulfilled(resolved),rejected。当处于pending状态的时候,可以转移到fulfilled(resolved)或者rejected状态。当处于fulfilled(resolved)状态或者rejected状态的时候,就不可变。

promise英文译为承诺,也就是说promise的状态一旦发生改变,就永远是不可逆的。

②一个promise必须有一个then方法,then方法接受两个参数:

promise.then(onFulfilled, onRejected)

其中onFulfilled方法表示状态从pending——>fulfilled(resolved)时所执行的方法,而onRejected表示状态从pending——>rejected所执行的方法。

③为了实现链式调用,then方法必须返回一个promise

promise2 = promise1.then(onFulfilled, onRejected)

四、实现一个符合Promise/A+规范的Promise

1.初始版本myPromse

function myPromise(constructor){
    let self = this;
    self.status = "pending";     //定义状态改变前的初始状态
    self.value = undefined;        //定义状态为resolved的时候的状态
    self.reason = undefined;    //定义状态为rejected的时候的状态
    function resolve(value){
        //两个==="pending",保证了状态的改变是不可逆的
       if(self.status === "pending"){
          self.value = value;
          self.status = "resolved";
       }
    }
    function reject(reason){
        //两个==="pending",保证了状态的改变是不可逆的
       if(self.status === "pending"){
          self.reason = reason;
          self.status = "rejected";
       }
    }
    //捕获构造异常
    try{
       constructor(resolve, reject);
    }catch(e){
       reject(e);
    }
}

同时,需要在myPromise的原型上定义链式调用的then方法:

myPromise.prototype.then = function(onFullfilled, onRejected){
   let self = this;
   switch(self.status){
      case "resolved":
        onFullfilled(self.value);
        break;
      case "rejected":
        onRejected(self.reason);
        break;
      default:       
   }
}

上述就是一个初始版本的myPromise,在myPromise里发生状态改变,然后在相应的then方法里面根据不同的状态可以执行不同的操作。

var p = new myPromise(function(resolve, reject){resolve(1)});
p.then(function(x){console.log(x)})
//输出1

但是这里myPromise无法处理异步的resolve.比如:

var p = new myPromise(function(resolve,reject){
    setTimeout(function(){resolve(1)},1000)
});
p.then(function(x){console.log(x)})
//无输出

2.简单代码实现promise

class PromiseM {
    constructor (process) {
        this.status = 'pending';
        this.msg = '';
        process(this.resolve.bind(this), this.reject.bind(this));
        return this;
    }
    resolve (val) {
        this.status = 'fulfilled';
        this.msg = val;
    }
    reject (err) {
        this.status = 'rejected';
        this.msg = err;
    }
    then (fufilled, reject) {
        if(this.status === 'fulfilled') {
            fufilled(this.msg)
        }
        if(this.status === 'rejected') {
            reject(this.msg)
        }
    }
}

// 测试代码

var mm = new PromiseM(function(resolve, reject){
    resolve('123');
});
mm.then(function(success){
    console.log(success);
},function(){
    console.log('fail!');
});