es5实现Promise---具体实现

1、正常使用Promise

var p = new Promise(function(resolve, reject){
    console.log('执行')
    setTimeout(function(){
        resolve(2)
    }, 1000)
})
p.then(function(res){
    console.log('suc',res)
},function(err){
    console.log('err',err)
})

同步实现 

2、首先实现三种状态:等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected)。

function MyPromise(executor){
    var _this = this
    _this.state = 'pending'; //状态
    _this.value = undefined; //成功结果
    _this.reason = undefined; //失败原因
    function resolve(value) {
        if(_this.state=='pending'){
             _this.state = 'fulfilled'
             _this.value = value
        }
    }
    function reject(reason) {
        if(_this.state=='pending'){
            _this.state = 'rejected'
             _this.value = reason
        }
    }
    try {                     //executor也会可能存在异常,用try/catch来捕获异常情况:
        executor(resolve, reject);
    } catch (e) {
        reject(e);
    }
}

//实例化MyPromise时,构造函数会马上调用传入的执行函数executor
let p = new Promise((resolve, reject) => {
    console.log('执行了');
});

3、then实现:当Promise的状态改变之后,不管成功还是失败,都会触发then回调函数。因此,then的实现就是根据状态的不同,来调用不同处理终值的函数。

MyPromise.prototype.then = function (onFulfilled, onRejected) {
    if(this.state === 'fulfilled'){
        onFulfilled(this.value)
    }
    if(this.state === 'rejected'){
        onRejected(this.reason)
    }
};

异步实现

4、如何让MyPromise来支持异步呢?可以参考发布订阅模式,在执行then方法的时候,如果当前还是PENDING状态,就把回调函数寄存到一个数组中,当状态发生改变时,去数组中取出回调函数。

将then里面的两个函数储存起来,由于一个promise可以有多个then,所以存在同一个数组内。成功或者失败时,forEach调用它们

function MyPromise(executor) {
    this.onFulfilled = [];//成功的回调
    this.onRejected = []; //失败的回调
}

当then执行时,如果还是PENDING状态,我们不是马上去执行回调函数,而是将其存储起来:

MyPromise.prototype.then = function (onFulfilled1, onRejected1) {
    if(this.state === 'pending'){
        this.onFulfilled.push(onFulfilled1)
        this.onRejected.push(onRejected1)
    }
};

存储起来后,当resolve或者reject异步执行的时候就可以来调用了 

function resolve(value) {
    if(_this.state === PENDING){
        _this.state = FULFILLED
        _this.value = value
        _this.onFulfilled.forEach(fn => fn( _this.value))
    }
}
function reject(reason) {
    if(_this.state === PENDING){
        _this.state = REJECTED
        _this.reason = reason
        _this.onRejected.forEach(fn => fn( _this.reason))
    }
}

https://zhuanlan.zhihu.com/p/144058361

https://my.oschina.net/u/2436852/blog/1837552

5、then链式调用

  1. 每个then方法都返回一个新的Promise对象(原理的核心)
  2. 如果then方法中显示地返回了一个Promise对象就以此对象为准,返回它的结果
  3. 如果then方法中返回的是一个普通值(如Number、String等)就使用此值包装成一个新的Promise对象返回。
  4. 如果then方法中没有return语句,就视为返回一个用Undefined包装的Promise对象
  5. 若then方法中出现异常,则调用失败态方法(reject)跳转到下一个then的onRejected
  6. 如果then方法没有传入任何回调,则继续向下传递(值的传递特性)
//1、
MyPromise.prototype.then = function (onFulfilled, onRejected) {
    let promise2 = new Promise((resolve, reject)=>{
    })
    return promise2
}

判断是普通值还是Promise对象用resolvePromise函数(这个函数可以复用)

MyPromise.prototype.then = function (onFulfilled, onRejected) {
    let promise2=new MyPromise((resolve,reject)=>{
        if(this.state === 'fulfilled'){
             let x=onFulfilled(this.value)
             resolvePromise(promise2,x,resolve,reject);
        }
        if(this.state === 'rejected'){
            let x= onRejected(this.reason)
            resolvePromise(promise2,x,resolve,reject);
        }
        if(this.state === 'pending'){
            this.onFulfilled.push(()=>{
                let x=onFulfilled(this.value)
                resolvePromise(promise2,x,resolve,reject);                
            })
            this.onRejected.push(()=>{
                let x=onRejected(this.reason)
                resolvePromise(promise2,x,resolve,reject); 
            })
        }
    }))
    return promise2;
};

 then的回调是异步执行的,因此需要把onFulfilled和onRejected执行放到异步中去执行,同时做一下错误的处理:

 onFulfilled或onRejected不能同步被调用,必须异步调用。用setTimeout解决异步问题

if(_this.state === FULFILLED){
    setTimeout(()=>{
        try {
            let x = onFulfilled(_this.value)
            resolvePromise(promise2, x, resolve, reject)
        } catch (error) {
            reject(error)
        }
    })
} else if(_this.state === REJECTED){
    setTimeout(()=>{
        try {                    
            let x = onRejected(_this.reason)
            resolvePromise(promise2, x ,resolve, reject)
        } catch (error) {
            reject(error)
        }
    })
} else if(_this.state === PENDING){
    _this.onFulfilled.push(()=>{
        setTimeout(()=>{
            try {                        
                let x = onFulfilled(_this.value)
                resolvePromise(promise2, x, resolve, reject)
            } catch (error) {
                reject(error)
            }
        })
    })
    _this.onRejected.push(()=>{
        setTimeout(()=>{
            try {                        
                let x = onRejected(_this.reason)
                resolvePromise(promise2, x ,resolve, reject)
            } catch (error) {
                reject(error)
            }
        })
    })
}

6、Promise.all()方法

Promise.all 接收一个 promise 对象的数组作为参数,当这个数组里的所有 promise 对象全部变为resolve或 有 reject 状态出现的时候,它才会去调用 .then 方法,它们是并发执行的。

7、Promise.race()方法

当想要实现一个方法,每次传入多个请求,哪个先返回就取消其他的,使用先返回的值

https://www.jianshu.com/p/90b6280dd1b6

8、Promise.resolve()方法 

有时需要将现有对象转为 Promise 对象,Promise.resolve方法就起到这个作用。

//resolve方法
MyPromise.resolve = function(val){
  return new Promise((resolve,reject)=>{
    resolve(val)
  });
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值