Promise的使用和实现

Promise的使用和特点

  • Promise是一个构造函数,接收一个函数(executor)作为参数,这个函数的参数有两个,resolve,reject
  • executor是立即执行函数,也就是在new Promise的时候,在Promise构造函数中直接被调用的
  • resolve, 是内部创建的函数,用户调用该函数可以让promise变成成功态(fufilled)
  • reject,是内部创建的函数,用户调用该函数可以让promise变成失败态(rejected)
  • promise有三种状态,默认是padding(等待态)、成功态(fufilled)、失败态(rejected)
  • 状态不可逆,一旦成功就不能失败,一旦失败就不能成功
  • 常用的then方法
    • 是原型方法
    • then方法调用接收两个参数作为参数,1. onFulfilled / 2. onRejected
    • then方法支持链式调用,可以一直.then().then()....
    • then方法的两个参数onFulfilled和onRejected的返回值,会作为下一次then的结果,如果返回值是一个promise,会解析这个promise,将promise的结果作为下一次then的结果
// 1. 创建promise实例
const p = new Promise((resolve, reject) => {
   // 直接执行的逻辑...
})
p.then(res => {
  return 100
  return new Promise((resolve, reject) => { resolve('hello') })
}).then(res => {
  console.log(res) // 100  / 'hello'
})

Promise A+ 规范,实现符合规范的promise

实现流程:
  1. Promise是一个构造函数,参数是一个executor函数
  2. executor的参数是resove和reject
  3. promise的三个状态,状态不可逆
  4. promise的两个值:1. 成功的value 2. 失败的原因reason
  5. executor中逻辑异步的处理,使用发布订阅的模式处理异步
  6. then方法中两个参数onFulfilled和onRejected的返回值的处理,使用resolvePromise来递归解析promise
实现代码:
class Promise {
    constructor(executor) {
        // promise 的三个状态 padding fulfilled rejected
        this.value = null;
        this.reason = null;
        this.fulfilledCbs = []; // 成功回调
        this.rejectedCbs = [];
        this.status = 'padding'

        const resolve = (value) => {
            if (this.status === 'padding') {
                this.status = 'fulfilled';
                this.value = value
                for (let i = 0; i < this.fulfilledCbs.length; i++) {
                    const fn = this.fulfilledCbs[i];
                    fn()
                }
            }
        }

        const reject = (reason) => {
            if (this.status === 'padding') {
                this.status = 'rejected'
                this.reason = reason
                for (let i = 0; i < this.rejectedCbs.length; i++) {
                    const fn = this.rejectedCbs[i];
                    fn()
                }
            }
        }

        try {
            executor(resolve, reject)
        } catch (e) {
            reject(e)
        }
    }

    // then 方法返回一个新的promise,叫promsie2
    // then 方法中的回调函数返回值可以是普通值或者promsie,如果是promise,会解析promise的值作为下一次then的值
    then(onFulfilled, onRejected) {
        const isFunction = val => typeof val === 'function';
        onFulfilled = isFunction(onFulfilled) ? onFulfilled : (value) => value; // 将then的结果透传给下一次then
        onRejected = isFunction(onRejected) ? onRejected : (error) => {
            throw error
        }

        let promise2; // then方法返回的promise叫promise2
        if (this.status === 'padding') { // 说明executor中的逻辑是异步执行的
            promise2 = new Promise((resolve, reject) => {
                this.fulfilledCbs.push(() => {
                    setTimeout(() => {
                        try {
                            // then方法回调的返回值叫做x
                            const x = onFulfilled(this.value)
                            resovlePromise(promise2, x, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0);
                })

                this.rejectedCbs.push(() => {
                    setTimeout(() => {
                        try {
                            // then方法回调的返回值叫做x
                            const x = onRejected(this.reason)
                            resovlePromise(promise2, x, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0);
                })
            })
        } else if (this.status === 'fulfilled') {
            promise2 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    try {
                        // then方法回调的返回值叫做x
                        const x = onFulfilled(this.value)
                        resovlePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                }, 0);
            })

        } else if (this.status === 'rejected') {
            promise2 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    try {
                        // then方法回调的返回值叫做x
                        const x = onRejected(this.reason)
                        resovlePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                }, 0);
            })
        }
        return promise2;
    }
}

function resovlePromise(promise2, x, resolve, reject) {
    // 返回的x可能是一个promise,但是一定不能和promise2相同
    if (promise2 === x) {
        return reject(new TypeError("same promise"));
    }

    // 分析x的值,可能是一个普通的值,可能是一个promise

    // 1. 如果 x 是一个 promise,使用它的状态
    if (x instanceof Promise) {
        x.then(val => {
            // y有可能也是一个promise,递归解析
            resovlePromise(promise2, val, resolve, reject)
        }, reject)
    }

    if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
        try {
            let then = x.then;
            let flag = false;
            if (typeof then === 'function') {
                try {
                    // x 作为this调用then
                    then.call(x, y => {
                        if (!flag) {
                            resovlePromise(promise2, y, resolve, reject)
                            flag = true;
                        }
                    }, r => {
                        if (!flag) {
                            reject(r)
                            flag = true;
                        }
                    })
                } catch (e) {
                    if (!flag) {
                        reject(e)
                        flag = true;
                    }
                }
            } else {
                resolve(x)
            }
        } catch (e) {
            reject(e)
        }

    } else {
        resolve(x)
    }
}
测试promise
  1. 增加测试代码
Promise.deferred = function () {
    let def = {};
    def.promise = new Promise(function (resolve, reject) {
        def.resolve = resolve;
        def.reject = reject;
    });
    return def;
}
module.exports = Promise
  1. 安装测试包
npm install -g promises-aplus-tests 
promises-aplus-tests  promise.js
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容