面试-搬砖到城堡2-1:手写promise及知识点解析

95 阅读2分钟

Promise在日常的开发中频繁的使用到,并且在面试的过程中也会被当做知识点经常提问到

Promise概述

在Promise出现之前,我们会使用回调函数来处理异步操作的结果,回调函数本身并没有什么问题,只是当业务逻辑比较深且复杂时,会产生“回调地狱”,对后期的重构和维护很不友好

Promise的结构和使用

首先我们看看,Promise平时的使用,好帮助我们下面更好的去理解每个代码部分的效果和功能。详细的解答和思路都在注释内。

let exp = new Promise((resolve, reject) {
    console.log("Promise is running");
    setTimeout(()=>{
        resolve("Tom is coming")
    }, 2000)
})

exp.then((res) => {
    console.log(res); // Tom is coming 
}, (err) => {
    // 处理报错异常 接收reject的参数
})

Promise的三个状态(pending, fullfilled, rejected)

  • pending 进行中
  • fullfilled 已完成
  • rejected 截获报错信息并传递给reject
  • Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected,只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为已定型

具体实现

class MyPromise {
    static pending = "pending"
    static success = "fullfilled"
    static error = "rejected"
    
    contructor(executor) {
        // 初始化状态
        this.status = MyPromise.pending
        this.value  = undefined // 初始化值
        this.errMsg = undefined // 初始化错误信息
        this.callbacks = [] // 考虑到异步请求promise的状态还未完成变更的情况
        // 将需执行的函数当做传参传入自己的Promise中
        executor(this._resolve.bind(this), this._reject.bind(this))
    }
    
    // 因为异步请求先需要执行resolve或reject改变状态后才能拿到需要的值,所以暂将其存入callbacks中,等待其执行完毕,再执行callbacks中的内容。每调用一次then就会向callbacks中推入一个新的待执行的
    then(onFullfilled, onRejected) {
        this.callbacks.push({
            onFullfilled, onRejected})
    }
    // 已完成
    _resolve(value) {
        this.status =  MyPromise.success // 将状态更新为已完成
        this.value = value
        // 执行callbacks队列中的内容
        this.callbacks.forEach(cb => this._handler(cb))
    }
    // 报错
    _reject(err) {
        this.status = MyPromise.error
        this.errMsg = err
        this.callbacks.forEach(cb => this._handler(cb))
    }
    
    // 用来处理异步数组的 也就是this.callbacks
    _handler(cb) {
        const {onFullfilled, onRejected} = cb
        
        if(this.status === MyPromise.success && onFullfilled) {
            // 执行成功
            onFullfilled(this.value)
        }
        
        if(this.status === MyPromise.error && onRejected) {
            // 报错信息
            onRejected(this.errMsg)
        }
    }
}

后续更新链式调用 Promise.all等