记录一下学习promise,源码视频在里面

258 阅读3分钟

Promise

源码视频地址

理解Promise

  • 本质是一个构造函数,使用的时候需要new Promise
  • new的时候会触发执行器,执行器是同步的
  • 执行器有两个函数
    • resolve
    • reject
  • Promise的状态是padding、resolve、reject
    • 过程是padding->resolved 一旦改变不能更改
    • 过程是padding->rejected 一旦改变不能更改
    • 不能反过来

.then

  • 是异步的
  • 有两个方法
    • 第一个接受resolve的结果
    • 第二个是处理错误
  • 值得注意的是如果在.then里面处理了error,那么接下来的catch就不能捕获

.all

  • 返回一个数组,按顺序执行,如果有一个失败,那么他就会变化rejected
  • interable类型->Array Set Map
  • 场景:使用多个异步任务并发运行,他的结果是创建的承诺之后使用,等待所有任务的完成

.rach

  • 谁最先执行完成,那么就先返回执行结果
  • 处理请求资源的响应时间

async和await

  • async 的意思是当前这个异步函数与当前的程序是异步关系
  • await 等待Promise对象产出的结果

链式调用

  • 成功的条件
    • then return 普通的Javascript value
    • then return 新的promise成功态的结果 value
  • 失败的条件
    • then retuen 新的promise失败态的原因 reason
    • then 抛出了异常 throw new Error
  • Promise链式原理
    • JavaScript jQuery return this
    • then 不具备this
    • 返回新的Promise

手写Promise源码部分

// 定义好每种状态  根据Promise A+ 文档
const PENDING = 'PENDING', // 等待
    FULLFILLED = 'FULLFILLED', // 成功
    REJECTED = 'REJECTED' // 失败

function resolvePromise(promise2, x, resolve, reject) {
    console.log(promise2);
}

class MyPromise {
    constructor(executor) {
        this.status = PENDING; // 状态值
        this.value = undefined; // 
        this.reason = undefined;

        // 设置两个容器
        this.onFullfilledCallbacks = [];
        this.onRejectedCallbacks = [];

        // 把resolve,reject 定义在内部
        const resolve = (value) => {
            // 判断pending状态 成功改变状态 
            if (this.status === PENDING) {
                this.status = FULLFILLED
                this.value = value

                // 发布模式
                this.onFullfilledCallbacks.forEach(fn => fn())
            }
        }

        const reject = (reason) => {
            // 判断pending状态 失败改变状态 
            if (this.status === PENDING) {
                this.status = REJECTED
                this.reason = reason

                // 发布模式
                this.onRejectedCallbacks.forEach(fn => fn())

            }
        }

        // 处理捕获异常
        try {
            executor(resolve, reject)
        } catch (e) {
            reject(e)
        }

    }
    // resolve,reject 定义在外面可能在原型上 只能访问一次

    // .then 两个函数 onFullfilled  onRejected 即 成功 or 失败 需要用status 来判断 然后传 相对应的值
    then(onFullfilled, onRejected) {
        // 定义一个promise2 用于返回  编写链式调用
    	/**
         * 1.处理thorw new Error -> try catch
         * 2.setTimeout 处理 不能访问promise2 因为还没new出来 先执行了下面的resolvePromise 源码是微任务 				这里宏任务代替
         */
        // x 不确定是普通值 还是promsie
        let promise2 = new MyPromise((resolve, reject) => {

            if (this.status === FULLFILLED) {
                
                setTimeout(() => {
                    try {
                        let x = onFullfilled(this.value)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e);
                    }
                }, 0)
            }

            if (this.status === REJECTED) {
                setTimeout(() => {
                    try {
                        let x = onRejected(this.reason)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e);
                    }
                }, 0)

            }

            if (this.status === PENDING) {
                // 订阅模式
                this.onFullfilledCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onFullfilled(this.value)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (e) {
                            reject(e);
                        }
                    }, 0)

                })
                // 订阅模式
                this.onRejectedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onRejected(this.reason)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (e) {
                            reject(e);
                        }
                    }, 0)

                })
            }
        })

        return promise2

    }
}

module.exports = MyPromise

处理resolvePromise

function resolvePromise(promise2, x, resolve, reject) {
    if (promise2 === x) {
        return reject(new TypeError('Chaining cycle detected for promise #<MyPromise>'))
    }
    if (typeof x === 'object' && x !== null || typeof x === 'function') {
        try {
            let then = x.then // throw error 用try catch

            let called = false
            if (typeof then === 'function') { // 这里认为他就是Promise
                // 改变this指向 Promise 实例 有两个参数 即成功 失败的方法
                then.call(x, (y) => {
                    if (called) return
                    called = true
                    // resolve(y)  递归处理多层嵌套
                    resolvePromise(promise2, y, resolve, reject)
                }, (r) => {
                    if (called) return
                    called = true
                    reject(r)
                })
            } else {
                resolve(x)
            }
        } catch (e) {
            if (called) return
            called = true
            reject(e);
        }
    } else {
        resolve(x)
    }
}

处理不能渗透的问题

// 处理 .then().then().then() 不能渗透的问题 因为这是定义好的 所以 没定义的时候 需要给他一个值
onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : value => value
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

catch语法糖

模拟then 的方法 第一个参数空即可

catch(errorCallback) {
    return this.then(null, errorCallback)
}