手写实现 Promise/A+ 标准

简介: 手写实现 Promise/A+ 标准

前言


本文仅作为个人记录,文中可能存在不严谨的地方。


要了解更多可以看下这两篇文章:

史上最易读懂的 Promise/A+ 完全实现

promise/A+规范翻译以及手写实现


正文


Promise/A+ 的标准有哪些?

  1. 只有一个 then 方法,没有 catch、race、all 等方法。
  2. then 返回一个新的 Promise。
  3. 不同的 Promise 的实现需要相互调用。
  4. Promise 的状态有 pending、fullfilled、rejected 三种。初始状态是 pending ,可以由 pending 转化为 fullfilled 或者 rejected。一旦状态确定之后,不能再被改变。
  5. 更具体的官方标准,看这里


下面上代码

function MyPromise(executor) {
    const _this = this;
    // 状态
    _this.status = 'pending';
    // resolve 值
    _this.value = null;
    // reject 原因
    _this.reason = null;
    // resolve、reject 函数
    _this.onFullfilled = [];
    _this.onRejected = [];
    function resolve(value) {
        if (value instanceof MyPromise) {
            return value.then(resolve, reject);
        }
        // 其实这里采用 setTimeout 方式实现异步执行 onFullfilled/onRejected 不太符合 Event Loop 机制。下面 reject 同理。
        setTimeout(() => {
            // 只有状态为 pending 才能被改变
            if (_this.status == 'pending') {
                _this.value = value;
                _this.status = 'resolved';
                _this.onFullfilled.forEach(currentValue => currentValue(value));
            }
        }, 0);
    }
    function reject(reason) {
        setTimeout(() => {
            // 只有状态为 pending 才能被改变
            if (_this.status == 'pending') {
                _this.reason = reason;
                _this.status = 'rejected';
                _this.onRejected.forEach(currentValue => currentValue(reason));
            }
        }, 0);
    }
    // 注意:若执行过程出现异常,则捕获异常并执行 reject 函数。
    try {
        executor(resolve, reject)
    } catch (e) {
        reject(e);
    }
}
function resolvePromise(promise2, x, resolve, reject) {
    let then;
    let thenCallorThrow = false;
    if (promise2 === x) {
        return reject(new TypeError('same Promise!'))
    }
    if (x instanceof MyPromise) {
        if (x.status === 'pending') {
            x.then(value => {
                resolvePromise(promise2, value, resolve, reject)
            }, reject)
        } else {
            x.then(resolve, reject)
        }
        return
    }
    if ((x !== null) && ((typeof x === 'object') || (typeof x === 'function'))) {
        try {
            then = x.then;
            if (typeof then === 'function') {
                then.call(x, res => {
                    if (thenCallorThrow) return;
                    thenCallorThrow = true;
                    return resolvePromise(promise2, res, resolve, reject);
                }, err => {
                    if (thenCallorThrow) return;
                    thenCallorThrow = true;
                    return reject(err)
                })
            } else {
                resolve(x);
            }
        } catch (e) {
            if (thenCallorThrow) return;
            thenCallorThrow = true;
            return reject(e)
        }
    } else {
        return resolve(x)
    }
}
MyPromise.prototype.then = function (onFullfilled, onRejected) {
    const _this = this;
    let promise2;   // promise.then() 返回一个 promise 对象
    // Promise 值的穿透处理:
    // 场景如: new Promise(resolve => resolve('abc')).then().catch().then(res => {console.log('print abc')})
    onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : val => val;
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
    switch (_this.status) {
        case 'pending':
            promise2 = new MyPromise((resolve, reject) => {
                _this.onFullfilled.push(value => {
                    try {
                        let x = onFullfilled(value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e)
                    }
                });
                _this.onRejected.push(reason => {
                    try {
                        let x = onRejected(reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e)
                    }
                });
            })
        case 'resolved':
            promise2 = new MyPromise((resolve, reject) => {
                setTimeout(() => {
                    try {
                        let x = onFullfilled(_this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e)
                    }
                });
            })
        case 'rejected':
            promise2 = new MyPromise((resolve, reject) => {
                setTimeout(() => {
                    try {
                        let x = onRejected(_this.reason);
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                });
            })
        default:
            break;
    }
    return promise2;
}
// Promise 标准里面没有 catch、race、all 等方法,只有一个 then 方法
MyPromise.prototype.catch = function (onRejected) {
    return this.then(null, onRejected)
}
new MyPromise((resolve, reject) => {
    resolve('right');
}).then(res => {
    console.log(res)
}, err => {
    console.warn(err)
})


目录
相关文章
|
前端开发
手写基础 promise
手写基础 promise
66 0
|
存储 前端开发
|
前端开发
Promise的用法&原理&手写实现-2
Promise的用法&原理&手写实现-2
42 1
|
5月前
|
存储 前端开发 API
技术笔记:Promise的原理探究及手写Promise
技术笔记:Promise的原理探究及手写Promise
34 0
|
6月前
|
前端开发 JavaScript API
手写promise
手写promise
40 0
|
前端开发 JavaScript API
Promise的用法&原理&手写实现-1
Promise的用法&原理&手写实现-1
54 0
|
资源调度 前端开发 JavaScript
带你读《现代Javascript高级教程》二十七、实现符合Promise/A+规范的Promise(4)
带你读《现代Javascript高级教程》二十七、实现符合Promise/A+规范的Promise(4)
|
存储 前端开发 JavaScript
带你读《现代Javascript高级教程》二十七、实现符合Promise/A+规范的Promise(1)
带你读《现代Javascript高级教程》二十七、实现符合Promise/A+规范的Promise(1)
|
前端开发 JavaScript
带你读《现代Javascript高级教程》二十七、实现符合Promise/A+规范的Promise(6)
带你读《现代Javascript高级教程》二十七、实现符合Promise/A+规范的Promise(6)
|
前端开发 JavaScript
带你读《现代Javascript高级教程》二十七、实现符合Promise/A+规范的Promise(2)
带你读《现代Javascript高级教程》二十七、实现符合Promise/A+规范的Promise(2)