首页 前端知识 Promise链式调用原理及实现(TS)

Promise链式调用原理及实现(TS)

2024-05-20 14:05:13 前端知识 前端哥 155 732 我要收藏

Promise 是一种 JavaScript 异步编程的解决方案,它可以避免回调函数嵌套和代码可读性差的问题。Promise 是一个表示异步操作的对象,它有三种状态:Pending(等待态)、Resolved(成功态)、Rejected(失败态)。

请添加图片描述

Promise 的原理可以分为以下几个部分:

  1. Promise 对象的状态可以从 Pending 转变为 Resolved 或 Rejected,但一旦状态发生变化就无法再次改变。
  2. Promise 对象有一个 then 方法,可以注册 Resolved 或 Rejected 状态变化后的回调函数,它返回的是一个新的 Promise 对象。
  3. then 方法接受两个回调函数作为参数,第一个函数用于处理 Resolved 状态,第二个函数用于处理 Rejected 状态。
  4. 如果 then 方法的回调函数返回一个 Promise 对象,那么 then 方法返回的新 Promise 对象会等待该 Promise 对象的状态变化,然后根据该 Promise 对象的状态再次改变自身状态。
  5. 如果 then 方法的回调函数返回一个非 Promise 对象的值,那么 then 方法返回的新 Promise 对象状态为 Resolved,值为该非 Promise 对象的值。
  6. 如果 then 方法的回调函数抛出一个异常,那么 then 方法返回的新 Promise 对象状态为 Rejected,值为该异常。

Promise 的实现依赖于 JavaScript 的事件循环机制,它使用微任务(microtask)和宏任务(macrotask)来管理异步操作的执行顺序。当 Promise 对象的状态变化时,它会根据 Promise 对象的状态和注册的回调函数类型(Resolved 或 Rejected)将回调函数放入微任务队列或宏任务队列中,等待事件循环机制调度执行。

下面是代码实现过程
使用ts能够更好的对类进行标记与规范,这里使用了泛型类来实现的。

export default class CustomPromise<T> {
    private status: "pending" | "fulfilled" | "rejected" = "pending";
    private results: T | undefined;
    private error: any;
    private resolveCbs: ((results: T) => void)[] = [];
    private rejectCbs: ((error: any) => void)[] = [];

    constructor (executor: (resolve: (results: T) => void, reject: (error: any) => void) => void) {
        executor(this.resolve.bind(this), this.reject.bind(this))
    }
    // pending => fulfilled
    private resolve (results: T) {
        if (this.status === "pending") {
            this.status = "fulfilled"
            this.results = results
            this.resolveCbs.forEach(cb => cb(results))
        }
    }
    // pending => rejected
    private reject (error: any) {
        // console.log("reject:外", error);
        // console.log(this.rejectCbs);
        if (this.status === "pending") {
            this.status = "rejected"
            this.error = error
            this.rejectCbs.forEach(cb => cb(error))
        }
    }
    // 执行then 回调
    public then (onSuccessFn?: (results: T | undefined) => void, onErrorFn?: (error: any) => void) {
        // 链式调用 => return Promise
        // 如果 then 方法的回调函数返回一个 Promise 对象,那么 then 方法返回的新 Promise 对象会等待该 Promise 对象的状态变化,然后根据该 Promise 对象的状态再次改变自身状态。
        // 如果 then 方法的回调函数返回一个非 Promise 对象的值,那么 then 方法返回的新 Promise 对象状态为 Resolved,值为该非 Promise 对象的值。
        // 如果 then 方法的回调函数抛出一个异常,那么 then 方法返回的新 Promise 对象状态为 Rejected,值为该异常。
        const promise = new CustomPromise((resolve, reject) => {
            if (this.status === "fulfilled") {
                // 这里的 try catch 是为了验证.then函数是否能正常执行,以下同
                try {
                    const results = onSuccessFn ? onSuccessFn(this.results) : undefined
                    resolve(results)
                } catch (error) {
                    reject(error)
                }
            }
            else if (this.status === "rejected") {
                try {
                    const results = onErrorFn ? onErrorFn(this.error) : undefined;
                    resolve(results)
                } catch (error) {
                    reject(error)
                }
            }
            else {
                this.resolveCbs.push((results) => {
                    try {
                        const newResults = onSuccessFn ? onSuccessFn(results) : undefined
                        resolve(newResults)
                    } catch (error) {
                        reject(error)
                    }
                })
                this.rejectCbs.push((error) => {
                    console.log(error);
                    try {
                        const newResult = onErrorFn ? onErrorFn(error) : undefined;
                        resolve(newResult)
                    } catch (error) {
                        reject(error)
                    }
                })
            }
        })
        return promise
    }
    // 执行catch 回调
    public catch (onErrorFn?: (results: any) => void) {
        return this.then(undefined, onErrorFn)
    }
}

重点:
1、要对then函数深度解读
2、JavaScript 的事件循环机

转载请注明出处或者链接地址:https://www.qianduange.cn//article/8975.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!