promise基本实现

Promise基本实现

promise state状态的描述

A promise must be in one of three states: pending, fulfilled, or rejected.
     1),When pending, a promise:may transition to either the fulfilled or rejected state.
     2),When fulfilled, a promise:must not transition to any other state.   must have a value, which must not change.
     3),When rejected, a promise:must not transition to any other state.must have a reason, which must not change.

代码实现

const PENDING = 'pending';
const REJECTED = 'rejected';
const FULFILLED = 'fulfilled';
class Promise{
    constructor(executor) {
        this.status = PENDING;
        this.value = undefined;
        this.reason = undefined;
        const resolve = (value) => {
            if (this.status === FULFILLED) return;
            this.value = value;
            this.status = FULFILLED;
        }
        const reject = (reason) => {
            if (this.status === REJECTED) return;
            this.reason = reason;
            this.status = REJECTED;
        }
        try {
            executor(resolve, reject);
        } catch (e) {
            reject(e)
        }
    }
}

promise then method

描述

  • then返回的必须是一个Promise这样才能实现promise的链式调用
    代码实现如下
then(onFulfilled, onRejected) {
  const promise2 = new Promise1((resolve, reject)=>{
  });
  return promise2
}
  • A promise’s then method accepts two arguments:
promise.then(onFulfilled, onRejected)
  • then中的回调函数的返回值,决定了下一个then的行为:因此要特殊处理
    • then中的参数为函数,then中回调函数的返回值,会传递个下一个then的回调函数中的形参。此时分两种情况
      1,被then中失败函数捕获
      上一个返回的是失败态的Promise或者抛出异常,会被下一个一个then中的失败所捕获
      // Promise失败状态
         Promise.reject('1').then((v)=>{
         	console.log(v); //不走这里
         }, (r)=>{
         console.log(r); // 1
         })
         // 抛出异常错误
         Promise.resolve('1').then(()=>{
         	return throw new Error('error')
         }).then(()=>{
         }, 
         (r)=>{
         console.log(r); //会捕获到上一个then中抛出的错误
         })
      
      2,被then中成功函数捕获;
      上一个返回的成功的promise或者说上一个的失败回调返回的是一个普通的值,会被下一个then的成功所捕获 这里的普通值指的是非promise, 非错误,非异常
      Promise.reject('1').then(()=>{
      }, (r)=>{
      return 'pre then error'
      }).then((v)=>{
      console.log(v); //pre then error捕获上一个then失败函数中返回的普通值
      })
      
    • then中的参数为非函数,
      因为then没有传递值或者说值不是函数,因此值向下传递,也就是常说的值的穿透问题
    // 以下是原生Promise的行为
     Promise.resolve('1').then().then().then((res)=>{
     console.log(res); //1,
     })    
    
    • then中回调函数非返回值为Promise
    // then中返回成功的promise
    Promise.resolve('1').then(v=>{
    	return new Promise((resolve,reject)=>{
    		resolve('ok')
    	})
    }).then((v)=>{
    console.log(v); //ok
    });
    
    //then中返回promise失败态
    Promise.resolve('1').then(v=>{
    	return new Promise((resolve,reject)=>{
    		reject('reject')
    	})
    }).then((v)=>{
       console.log(v, 'onFulfilled'); //不走这里
    },(r)=>{
    	console.log(r, 'onRejected');//reject onRejected
    })
    

then 方法的完整实现

then(onFulfilled, onRejected) {
        const promise2 = new Promise1((resolve, reject) => {
            // 处理参数为非函数的情况
            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
            // If `onRejected` is not a function and `promise1` is rejected, `promise2` must be rejected with the same reason.
            onRejected = typeof onRejected === 'function' ? onRejected : r => reject(r); 
             // 以下处理Promise状态异步改变的情况
             // 需要then的回调函数暂存起来
             // 需要对then函数的回调函数的返回值做处理 ,因为返回值有可能是Promise
             // onFulfilled or onRejected must not be called until the execution context stack contains only platform code. [3.1].
             // 因此这里需要异步来处理 
            
            if (this.status === PENDING) {
                this.onRejectedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            const x = onRejected(this.reason);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    }, 0);
                });
            
                this.onFulfilledCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            const x = onFulfilled(this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    }, 0);
                });
            }
            // 
            if (this.status === FULFILLED) {
                setTimeout(() => {
                    try {
                        const x = onFulfilled(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0);
            }
            if (this.status === REJECTED) {
               // const x = onRejected(this.reason); // 要求必须要在同意栈中调用
                setTimeout(() => {
                    try {
                        const x = onRejected(this.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0);
            }
        });
        return promise2;
    }

platform code的意思

Here “platform code” means engine, environment, and promise implementation code. In practice, this requirement ensures that onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack. This can be implemented with either a “macro-task” mechanism such as setTimeout or setImmediate, or with a “micro-task” mechanism such as MutationObserver or process.nextTick. Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or “trampoline” in which the handlers are called.

The Promise Resolution Procedure

  • promise2 和x不能相等,如果相等就用TypeError作为reject的值返回
  • 如果x 不是对象或者函数 直接resolve(x);
  • 如果x是对象或者函数 如果let then = x.then
    • 1、如果then为对象则resolve(x)
    • 2、如果then为函数,x为then的this,y为then的value; r为then的reason,直接reject(r)返回失败的结果
      注意 这里的y有可能还是Promise,因此需要对y进行resolvePromise处理;
      还需要注意的是,有可能内部调用promise改变promsie的状态,因此需要做冻结处理,次数再取then的地方加个开关
resolvePromise 方法的实现
const resolvePromise = (promise2, x, resolve, reject) => {
    if (promise2 === x) {
        return reject(new TypeError('不能循环引用'));
    }
    // x为对象或者函数
    if ((x !== null && typeof x === 'object') || typeof x === 'function') {
        let called = false; //加开关防止then中的状态被篡改
        try {
            // x为函数
            let then = x.then;
            if (typeof then === 'function') {
                then.call(x,
                    (y) => {
                        if (called) return;
                        called = true;
                        resolvePromise(promise2, y, resolve, reject); //继续递归处理y
                    },
                    (r) => {
                        if (called) return;
                        called = true;
                        reject(r)
                    },
                )
                //x为对象
            } else {
                resolve(x);
            }
        } catch (e) {
            if (called) return;
            called = true;
            reject(e);
        }
    // x为普通值
    }else {
        resolve(x);
    }
}

Promise基本代码的实现

const PENDING = 'pending';
const REJECTED = 'rejected';
const FULFILLED = 'fulfilled';
const resolvePromise = (promise2, x, resolve, reject) => {
    if (promise2 === x) {
        return reject(new TypeError('不能循环引用'));
    }
    // x为对象或者函数
    if ((x !== null && typeof x === 'object') || typeof x === 'function') {
        let called = false;
        try {
            // x为函数
            let then = x.then;
            if (typeof then === 'function') {
                then.call(x,
                    (y) => {
                        if (called) return;
                        called = true;
                        resolvePromise(promise2, y, resolve, reject)
                    },
                    (r) => {
                        if (called) return;
                        called = true;
                        reject(r)
                    },
                )
                //x为对象
            } else {
                resolve(x);
            }
        } catch (e) {
            if (called) return;
            called = true;
            reject(e);
        }
    // x为普通值
    }else {
        resolve(x);
    }
}
class Promise1 {
    constructor(executor) {
        this.status = PENDING;
        this.value = undefined;
        this.reason = undefined;
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];
        const resolve = (value) => {
            if (this.status === FULFILLED) return;
            this.value = value;
            this.status = FULFILLED;
            this.onFulfilledCallbacks.forEach(fn => fn());
        }
        const reject = (reason) => {
            if (this.status === REJECTED) return;
            this.reason = reason;
            this.status = REJECTED;
            this.onRejectedCallbacks.forEach(fn => fn())
        }
        try {
            executor(resolve, reject);
        } catch (e) {
            reject(e)
        }
    }
    then(onFulfilled, onRejected) {
        const promise2 = new Promise1((resolve, reject) => {
            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
            onRejected = typeof onRejected === 'function' ? onRejected : r => reject(r); // If `onRejected` is not a function and `promise1` is rejected, `promise2` must be rejected with the same reason.
            if (this.status === PENDING) {
                this.onRejectedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            const x = onRejected(this.reason);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    }, 0);
                });
                this.onFulfilledCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            const x = onFulfilled(this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    }, 0);
                });
            }
            if (this.status === FULFILLED) {
                setTimeout(() => {
                    try {
                        const x = onFulfilled(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0);
            }
            if (this.status === REJECTED) {
                setTimeout(() => {
                    try {
                        const x = onRejected(this.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0);
            }
        });
        return promise2;
    }
}
Promise1.deferred = function () {
    const dfd = {};
    dfd.promise = new Promise1((resolve, reject) => {
        dfd.resolve = resolve;
        dfd.reject = reject;
    });
    return dfd;
}
module.exports = Promise1;

测试

用promises-aplus-tests这包来测试proise代码

下载包
npm install promises-aplus-tests -g

运行测试文件
promises-aplus-tests 文件名

promise其他方法的实现待续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值