简单理解JavaScript中的Promise

1、概念

Promise 是 JavaScript 中用于异步编程的一种对象,解决了回调地狱的问题。
一个 Promise 有三种状态:

  1. Pending(等待):初始状态,既不是成功,也不是失败状态。
  2. Fulfilled(已成功):意味着操作成功完成。
  3. Rejected(已失败):意味着操作失败。

Promise是一个构造函数,接受一个函数作为参数,该函数的两个参数分别是resolve和reject,它们是两个函数。

resolve函数的作用是,将Promise对象的状态从“等待”变为“成功”(即从 pending 变为 fulfilled)

reject函数的作用是,将Promise对象的状态从“等待”变为“失败”(即从 pending 变为 rejected)

Promise 的一个常见用途是处理异步操作,比如网络请求、文件读写等。使用 Promise 可以避免回调地狱(callback hell),让代码更加清晰和易于维护。

2、Promise的实例方法

Promise的实例有 .then(), .catch(), 和 .finally() 这些方法来处理异步操作的结果。

  • .then():当 Promise 状态变为 Fulfilled 时,会调用这个方法。then函数接收两个参数,一个onResolved(Promise 的状态为成功时候调用),一个onRejected(Promise 的状态为失败时候调用)。
  • .catch():当 Promise 状态变为 Rejected 时,会调用这个方法。它接受一个函数作为参数,这个函数会在 Promise 失败时执行。(catch方法实际就是then方法只传onRejected时的语法糖)
  • .finally():无论 Promise 的状态是 Fulfilled 还是 Rejected,都会调用这个方法。它接受一个函数作为参数,这个函数会在 Promise 完成后执行,无论成功还是失败。

3、Promise的静态方法

  •  Promise.all()           // 并发处理多个异步任务,所有任务都执行成功才能得到结果

  •  Promise.race()       // 并发处理多个异步任务,只要有一个任务执行完就得到结果

  •  Promise.any()        // 并发处理多个异步任务,只要有一个任务执行成功就得到结果

  •  Promise.resolve()  // 将现有对象转为fulfilled状态的 Promise对象

  •  Promise.reject()     // 将现有对象转为rejected状态的 Promise对象

4、手写一个函数实现Promise

//立使用立即执行函数,实现闭包
var MyPromise = (function(window){
    // 三个状态会多次使用时,所以不建议写死
    const PENDING = 'pending';  // 等待
    const RESOLVED = 'resolved';  // 成功
    const REJECTED ='rejected';  // 失败
    // 返回一个class,可以实例化
    return class MyPromise {
        // 构造函数,参数是一个回调函数
        constructor(fn){
            this.status = PENDING;  // 初始状态为等待
            this.value = undefined;  // 成功状态的数据
            this.reason = undefined;  // 失败状态的数据
            // 异步操作
            this.onFulfilledCallbacks = [];  // 成功的回调函数数组
            this.onRejectedCallbacks = [];  // 失败的回调函数数组
            // 声明成功的方法
            const resolve = value => {
                // 只有状态为等待时才能修改状态
                if(this.status == PENDING){
                    this.status = RESOLVED // 修改状态为成功
                    this.value = value  // 保存成功状态的数据
                    // 状态为成功时,执行成功的回调函数
                    this.onFulfilledCallbacks.forEach(cb => cb())
                }
            }
            // 声明失败的方法
            const reject = value => {
                // 只有状态为等待时才能修改状态
                if(this.status == PENDING){
                    this.status = REJECTED // 修改状态为失败
                    this.reason = value  // 保存失败状态的数据
                    // 状态为失败时,执行失败的回调函数
                    this.onRejectedCallbacks.map(cb => cb())
                }
            }

            // 同步代码的错误处理,要使用try...catch
            try{
                fn(resolve, reject)  // 调用构造函数的参数并传入两个方法
            } catch(error){
                reject(error)  // 出现错误就直接把状态修改为失败
            }
        }
        // then方法,接收两个参数,分别是成功和失败的回调函数
        then(onFulfilled, onRejected){
            // 如果状态为成功执行参数1的回调函数
            if(this.status === RESOLVED){  
                onFulfilled && onFulfilled(this.value)
            }
            // 如果状态为失败执行参数2的回调函数
            if(this.status === REJECTED){  
                onRejected && onRejected(this.reason)  // &&是为了避免onRejected为undefined的情况
            }
            // 如果状态为等待,则将回调函数保存到对应的数组中
            if(this.status == PENDING){  
                this.onFulfilledCallbacks.push(()=>{
                    onFulfilled && onFulfilled(this.value)
                })
                this.onRejectedCallbacks.push(()=>{
                    onRejected && onRejected(this.reason)
                })
            }
            return this  // 返回this,可以链式调用
        }

        // catch方法,接收一个参数,是失败的回调函数
        catch(onRejected){
            this.then(null,onRejected)  //失败就直接调用写好的then方法
            return this  // 返回this,可以链式调用
        }
        // finally方法,无论成功还是失败都会执行
        finally(cb){
            return this.then(() => cb(), () => cb())  // 
        }
    }
})(window)

使用该函数,为了模拟异步操作,使用延时器:

// 使用
new MyPromise((resolve, reject) => {
    setTimeout(() => {
        if (Math.random() > 0.5) {
            resolve('new Promise 成功')
        } else {
            reject('new Promise 失败')
        }
    },1000)
})
    .then(res => {
        console.log('then方法参数1:', res);
    }, err => {
        console.log('then方法参数2:', err);
    })
    .catch(err => {
        console.log('catch方法:', err);
    })
    .finally(() => {
        console.log('finally方法');
    })

当Math.random()随机数大于0.5时结果为成功,控制台显示如下:

当Math.random()随机数小于0.5时结果为失败,控制台显示如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值