实现一个符合promiseA+规范的promise

4 篇文章 0 订阅
本文详细介绍了Promise的原理和基本实现,以及其在解决异步问题中的关键作用,同时对比了callback和generator/co库。进阶版Promise实现解决了then同步执行和then回调返回值的问题,适合面试场景。
摘要由CSDN通过智能技术生成
关于异步的解决方案目前有四种:
  • callback(回调函数)
  • generato + co库
  • promise
  • async+await
promise的基本特点:
  1. promise代表的是承诺的意思 promise最核心的就是有三个状态,等待态(pending), 成功态(fulfilled)
    ,失败态(rejected)
  2. 状态只能从等待态改变成其他状态 ,不能从成功变成失败,也不能从失败变成成功
  3. 默认你传入的executor会立刻执行, 这个executor函数接受两个参数 resolve,reject 都是函数类型
  4. 在代码中发生异常也是会走失败的情况

封装基本的promise :

// 三个状态
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'
class Promise {
    constructor(executor) { // 用户传入一个executor
        this.status = PENDING;
        this.value = undefined;
        this.reason = undefined;
        this.onResolvedCallbacks = []; // 存放成功的回调的
        this.onRejectedCallbacks = []; // 存放失败的回调的
        const resolve = (value) => {
            if (this.status === PENDING) {
                this.status = FULFILLED
                this.value = value;
                this.onResolvedCallbacks.forEach(fn=>fn());
            }
        }
        const reject = (reason) => {
            if (this.status === PENDING) {
                this.status = REJECTED
                this.reason = reason;
                this.onRejectedCallbacks.forEach(fn=>fn());
            }
        }
        try {
            executor(resolve, reject); 
        } catch (e) {
            reject(e);
        }
    }
    then(onFulfilled, onRejected) { 
        //调用then的时候来判断成功还是失败
        if(this.status ===FULFILLED ){
            onFulfilled(this.value);
        }
        if(this.status === REJECTED){
            onRejected(this.reason)
        }
        if(this.status === PENDING){
            this.onResolvedCallbacks.push(()=>{
                onFulfilled(this.value);
            });
            this.onRejectedCallbacks.push(()=>{
                onRejected(this.reason);
            })
        }
    }
}

测试验证:

let promise = new Promise((resolve,reject)=>{ 
    setTimeout(()=>{
      resolve('1111');
    },1500)
});
promise.then((value)=>{ 
    console.log('success',value)
},(reason)=>{ 
    console.log('fail',reason)
})
promise.then((value)=>{ 
    console.log('success',value)
},(reason)=>{ 
    console.log('fail',reason)
})

封装完基本版本后,还存在的问题:
1.then不是异步的,如果直接调用resolve完后是同步执行,比如:

let promise = new Promise((resolve,reject)=>{ 
  resolve('1111');
});
promise.then((value)=>{ 
    console.log('success',value)
},(reason)=>{ 
    console.log('fail',reason)
})
promise.then((value)=>{ 
    console.log('success',value)
},(reason)=>{ 
    console.log('fail',reason)
})
console.log('end');

结果是先输出:success 1111,再试end
2.我们newPromise 直接resolve了 ,会将resolve的参数传递到了下一次then中,then中传递的成功和失败的回调的返回值, 会决定下一个then 走成功还是失败,比如:

let promise2 = new Promise((resolve,reject)=>{
    resolve('ok')
})

promise2.then(data=>{
    return 'next'
},()=>{
    return 'fail'
}).then((data)=>{
    console.log('success',data)
},(err)=>{
    console.log('fail',err)
})

该代码输出的正确结果,应该是 success next,但输出却是报错的,因为then并没有返回值
在这里插入图片描述

进阶版promise实现:
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'
function resolvePromise(promise2, x, resolve, reject) {
    if (x) {
        try {
                resolve(x); 
        } catch (e) {
            reject(e); 
        }
    } else {
        resolve(x); // 这里直接成功即可 普通值的情况
    }
}
class Promise {
    constructor(executor) {
        this.status = PENDING;
        this.value = undefined;
        this.reason = undefined;
        this.onResolvedCallbacks = []; // 存放成功的回调的
        this.onRejectedCallbacks = []; // 存放失败的回调的
        const resolve = (value) => {
            if(value instanceof Promise){
                return value.then(resolve,reject)
            }
            if (this.status === PENDING) {
                this.status = FULFILLED
                this.value = value;
                this.onResolvedCallbacks.forEach(fn => fn());
            }
        }
        const reject = (reason) => {
            if (this.status === PENDING) {
                this.status = REJECTED
                this.reason = reason;
                this.onRejectedCallbacks.forEach(fn => fn());
            }
        }
        try {
            executor(resolve, reject); 
        } catch (e) {
            reject(e);
        }
    }
    then(onFulfilled, onRejected) {
        let promise2 = new Promise((resolve, reject) => {
            if (this.status === FULFILLED) {
                setTimeout(() => {
                    try {
                        let x = onFulfilled(this.value);
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e) { // 执行对应的回调时发生异常就执行promise2的失败
                        reject(e);
                    }
                }, 0);
            }
            if (this.status === REJECTED) {
                setTimeout(() => {
                    try {
                        let x = onRejected(this.reason)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e) { // 执行对应的回调时发生异常就执行promise2的失败
                        reject(e);
                    }
                }, 0);
            }
            if (this.status === PENDING) {
                this.onResolvedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onFulfilled(this.value);
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (e) { // 执行对应的回调时发生异常就执行promise2的失败
                            reject(e);
                        }
                    }, 0)
                });
                this.onRejectedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onRejected(this.reason);
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (e) { // 执行对应的回调时发生异常就执行promise2的失败
                            reject(e);
                        }
                    }, 0)
                })
            }
        });

        return promise2
    }
}

结果:

let promise = new Promise((resolve,reject)=>{ 
  resolve('1111');
});
promise.then((value)=>{ 
    console.log('success',value)
},(reason)=>{ 
    console.log('fail',reason)
})
promise.then((value)=>{ 
    console.log('success',value)
},(reason)=>{ 
    console.log('fail',reason)
})
console.log('end');

能正确输出结果:在这里插入图片描述

let promise2 = new Promise((resolve,reject)=>{
    resolve('ok')
})

promise2.then(data=>{
    return 'next'
},()=>{
    return 'fail'
}).then((data)=>{
    console.log('success',data)
},(err)=>{
    console.log('fail',err)
})

正确输出结果:
在这里插入图片描述

当然上面进阶版的实现也不是最终完整版的,最终的版本会有很多类型判断,我也是把基本代码跑通了而已,面试的时候,基本版本就够用了,毕竟也不会给这么多时间你写,哈哈

补充:

promiseA+规范中只有then实现的规定,并没有规定其他方法的规则,比如Promise.resolve(),Promise.reject(),等Promise类上的静态方法的实现,起始都是基于promise实例的then去实现的,比如Promise.resolve()的实现如下:

Promise.resolve = function (value) {
        return new Promise((resolve) => {
            resolve(value)
        })
    }
Promise A是Promise/A规范的一部分,它定义了一种对Promise对象进行交互的方式。根据Promise/A规范一个Promise对象需要暴露一个遵循Promise/A协议的then方法。这样的设计使得Promise实现更加通用,因为只要一个对象暴露了符合规范的then方法,它就可以被视为Promise对象,而不必强制要求完全符合规范。这也使得符合Promise/A规范实现可以与不太规范但可用的实现能够很好地共存。 在Promise的解决过程中,[[Resolve]](promise, x)是一个抽象操作,它接收一个Promise对象和一个值作为输入。如果值x有then方法且看起来像一个Promise对象,那么解决过程将尝试让promise接收x的状态。否则,解决过程将使用x的值来完成(fulfilled)promise一个Promise代表一个异步操作的最终结果,通过它的then方法与Promise进行交互。then方法注册了两个回调函数,用于接收Promise的最终结果或导致Promise无法被完成(fulfilled)的原因。通常,第一个回调函数用于处理Promise的成功情况,第二个回调函数用于处理Promise的失败情况。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Promises/A+ 规范](https://blog.csdn.net/u014627807/article/details/120011719)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

codingWeb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值