理解promise

128 阅读3分钟

JavaScript 是单线程、异步、非阻塞、解释型脚本语言。实际开发中很多执行要基于异步任务,所以要解决异步的问题。

  • 异步编程方式:
    • 回调,但是回调多了代码会形成回调地狱
    • 发布订阅
    • 事件监听
    • Promise
    • generator
    • async/await-generator封装的语法糖

Promise

Promise实例支持链式调用,代码清晰,易于维护,低耦合

  • Promise源码的重点

    • 处理异步,保证代码按顺序执行
    • 处理链式调用,保证返回一个新的Promise实例
    • 处理resolve中传入的是一个新的Promise实例
    • 处理then方法中传入的执行函数返回的值为一个新的Promise实例
  • 分析

    • resolve是为下一个promise实例赋值和更改状态服务的
    • 规范状态只能从pending到fulfilled或者rejected,执行resolve和reject更改状态,即当前实例状态更改将不会再重复执行
    • 其实每一次返回的都是一个新的实例,并且收集函数数组中也最多只有一个等待执行回调函数,等待当前promise状态改变执行
  • 简单实现代码

const PENDING = 'pending';//等待状态
const FUFILLED = 'fulfilled';// 成功状态
const REJECTED = 'rejected';// 失败状态
class Promise {
    constructor(excutor) {
        this.state = PENDING;// 初始化状态
        this.value = undefined;// 初始化值
        this.result = undefined;// 初始化失败原因
        this.onFulfilledCB = [];// 成功状态回调收集函数数组
        this.onRejectedCB = [];// 失败装填回调收集函数数组
        // 状态pending=>fulfilled
        // 3---------处理传入的值为promise实例(需要拿到当前promise的状态和值)
        let resolve = (value) => {
            if (value && value.then && value instanceof Promise) {
                // 此时的resolve是最开始的promise的,通过then内部通过value内部的状态调用不同的状态函数进行赋值,和状态更改
                // 此处兼容value内部的是异步和同步(因为then内部已经处理好了)
                value.then(resolve, reject)
                return;
            }
            //这样状态只能改变一次,防止多次调用resolve
            if (this.state === PENDING) {
                this.state = FUFILLED;
                this.value = value;
                //此处将then中回调收集
                setTimeout(() => {
                    // this.value是需要在异步中使用的值
                    this.onFulfilledCB.forEach((cb) => {
                        cb(this.value)
                    })
                })
            }
        }
        // 状态pending=>rejected
        let reject = (result) => {
            //这样状态只能改变一次,防止多次调用resolve
            if (this.state == PENDING) {
                this.state = REJECTED;
                this.result = result;
                setTimeout(() => {
                    // this.value是需要在异步中使用的值
                    this.onRejectedCB.forEach(cb => {
                        cb(this.result)
                    })
                })
            }
        }

        try {
            // 执行函数
            excutor(resolve, reject)
        } catch (er) {
            reject(er);
        }
    }
    then(onFulfilled, onRejected) {
        //保证是一个函数
        onFulfilled = Object.prototype.toString.call(onFulfilled) === '[object Function]' ? onFulfilled : value => value;
        onRejected = Object.prototype.toString.call(onRejected) === '[object Function]' ? onRejected : result => {
            throw reason
        };
        // 当状态已经改变直接执行回调
        if (this.state == FUFILLED) {
            //2-------处理链式调用(返回一个新的p实例,并且将返回值通过resolve赋值给value,也就是下一次调用回调使用的value)
            return new Promise((resolve, reject) => {
                let x = onFulfilled(this.value);
                if (x instanceof Promise) {
                    x.then(resolve, reject);
                    return;
                }
                resolve(x)
            })

        }
        // 当状态已经改变直接执行回调
        if (this.state == REJECTED) {
            return new Promise((resolve, reject) => {
                let x = onRejected(this.result);
                if (x instanceof Promise) {
                    x.then(resolve, reject);
                    return;
                }
                reject(x)
            })
        }

        // 1--------处理异步
        // 2--------处理异步链式调用
        // 4--------处理返回值x为promise的情况(需要将返回的promise的状态和值传递下去)
        if (this.state == PENDING) {
            let _this = this;
            return new Promise((resolve, reject) => {
                _this.onFulfilledCB.push(() => {
                    let x = onFulfilled(_this.value);
                    if (x instanceof Promise) {
                        x.then(resolve, reject);
                        return;
                    }
                    //调用时给新的promise实例赋值
                    resolve(x)
                });
                _this.onRejectedCB.push(() => {
                    let x = onRejected(_this.result);
                    if (x instanceof Promise) {
                        x.then(resolve, reject);
                        return;
                    }
                    //调用时给新的promise实例赋值
                    reject(x)
                });
            })
        }
    }
    catch () {

    }
    //静态方法
    static resolve() {

    }
    static reject() {

    }
    static race() {

    }
    static all() {

    }
}