其他分享
首页 > 其他分享> > promise基本实现

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(onFulfilled, onRejected) {
  const promise2 = new Promise1((resolve, reject)=>{
  });
  return promise2
}
promise.then(onFulfilled, 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

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其他方法的实现待续

标签:基本,resolve,const,实现,promise2,promise,reject,return,onRejected
来源: https://blog.csdn.net/qq_38352648/article/details/120708884