现在es6的promise已经是用的很广泛的,可以有效的解决地域回调的问题。
那么现在我们可以制作一个简单的promise,让自己更加熟悉promise。

一.回顾promise

先我们需要了解一下promise的用法。以下demo

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可以处理异步操作。此外还可以链式调用

二.了解一下promise规范https://promisesaplus.com/

我们主要关心它的要求有一下几点:

1.一个promise必须有3个状态,pending,fulfilled(resolved),rejected当处于pending状态的时候,可以转移到fulfilled(resolved)或者rejected状态。当处于fulfilled(resolved)状态或者rejected状态的时候,就不可变。
2.一个promise必须有一个then方法,then方法接受两个参数:
3.为了实现链式调用,then方法必须返回一个promise

三.制作promise

接下来我们来制作简单的promise,以下将分几个版本,来循序渐进的增加内容

1) v1.0版本

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

同时在原型链上增加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:       
   }
}

然后测试一下

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

但是我们可以发现这边是没有异步过程的,即then里面是没有处理内容的

v1.1

增加异步功能

function myPromise(constructor){
    let self=this;
    self.status="pending" //定义状态改变前的初始状态
    self.value=undefined;//定义状态为resolved的时候的状态
    self.reason=undefined;//定义状态为rejected的时候的状态
    self.onFullfilledArray=[];
    self.onRejectedArray=[];
    function resolve(value){
       if(self.status==="pending"){
          self.value=value;
          self.status="resolved";
          self.onFullfilledArray.forEach(function(f){
                f(self.value);
                //如果状态从pending变为resolved,
                //那么就遍历执行里面的异步方法
          });
        
       }
    }
    function reject(reason){
       if(self.status==="pending"){
          self.reason=reason;
          self.status="rejected";
          self.onRejectedArray.forEach(function(f){
              f(self.reason);
             //如果状态从pending变为rejected, 
             //那么就遍历执行里面的异步方法
          })
       }
    }
    //捕获构造异常
    try{
       constructor(resolve,reject);
    }catch(e){
       reject(e);
    }
}
myPromise.prototype.then=function(onFullfilled,onRejected){
   let self=this;
   switch(self.status){
      case "pending":
        self.onFullfilledArray.push(function(){
             onFullfilled(self.value)
        });
        self.onRejectedArray.push(function(){
             onRejected(self.reason)
        });
        break;
      case "resolved":
        onFullfilled(self.value);
        break;
      case "rejected":
        onRejected(self.reason);
        break;
      default:       
   }
}

现在在来测试已经可以发出then了
但是现在还无法处理链式调用then

v1.3

增加then链式调用

v1.3.1

最简单的就是then返回一个对象,可以进行链式调用

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

一个简单的this就是promise对象本身,这样就可以了,按时this永远都是同一个promise对象,即then里的value永远都是相同的
因此我们需要返回一个新的promise

v1.3.2

promise.prototype.then = function(onFullfilled, onRejected) {

    var self = this
    let promise2

    switch (self.status) {
        case "pending":
            promise2 = new promise(function(resolve, reject) {
                self.onFullfilledArray.push(function() {
                    try {
                        let temple = onFullfilled(self.value)
                        resolve(temple)
                    } catch (e) {
                        reject(e)
                    }
                })
                self.onRejectedArray.push(function() {
                    try {
                        let temple = onRejected(self.reason);
                        resolve(temple)
                    } catch (e) {
                        reject(e) // error catch
                    }
                })
            })
            break;
        case "resolved":
            promise2 = new promise(function(resolve, reject) {
                try {
                    let temple = onFullfilled(self.value);
                    //将上次一then里面的方法传递进下一个Promise的状态
                    resolve(temple);
                } catch (e) {
                    reject(e); //error catch
                }
            })
            break;
        case "rejected":
            promise2 = new promise(function(resolve, reject) {
                try {
                    let temple = onRejected(self.reason);
                    //将then里面的方法传递到下一个Promise的状态里
                    resolve(temple);
                } catch (e) {
                    reject(e);
                }
            })
            break;
        default:
    }
    return promise2;
}

至此简单的promise已经完成了。但是这个promise还是有不少问题的,如then里面直接使用primise等。这些都是优化问题。
我们这样就知道了promise的运行机制了。

觉得不错的请点赞,谢谢。


DanielDemi
159 声望8 粉丝

开始前端之旅