You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
staticall(promiseArr){if(!Array.isArray(promiseArr)){consttype=typeofpromiseArr;returnnewTypeError(`TypeError: ${type}${values} is not iterable`)}returnnewMyPromise((resolve,reject)=>{letcounts=0;letresult=[];letlen=promiseArr.length;for(leti=0;i<len;i++){letinstance=promiseArr[i];// Promise.resolve(p)用于处理传入值不为Promise的情况MyPromise.resolve(instance).then(val=>{counts++;result[i]=val;if(counts===len){resolve(result);}},err=>{reject(err);})}})}
staticallSettled(promiseArr){if(!Array.isArray(promiseArr)){consttype=typeofpromiseArr;returnnewTypeError(`TypeError: ${type}${values} is not iterable`)}returnnewMyPromise((resolve,reject)=>{letcounts=0;letresult=[];letlen=promiseArr.length;for(leti=0;i<len;i++){letinstance=promiseArr[i];// Promise.resolve(p)用于处理传入值不为Promise的情况MyPromise.resolve(instance).then(res=>{counts++;result.push({status: "fulfilled",value: res});if(counts===len){resolve(result);}},err=>{counts++;result.push({status: "rejected",value: err});if(counts===len){resolve(result);}})}})}
staticany(promiseArr){if(!Array.isArray(promiseArr)){consttype=typeofpromiseArr;returnnewTypeError(`TypeError: ${type}${values} is not iterable`)}returnnewMyPromise((resolve,reject)=>{lethasOneResolved=false;letcounts=0;letlen=promiseArr.length;for(leti=0;i<len;i++){letinstance=promiseArr[i];// Promise.resolve(p)用于处理传入值不为Promise的情况MyPromise.resolve(instance).then(res=>{if(hasOneResolved)return;hasOneResolved=true;resolve(res);},err=>{counts++;if(counts===len){reject('AggregateError: All promises were rejected');}})}})}
Uh oh!
There was an error while loading. Please reload this page.
什么是Promise?
Promise 是异步编程的一种解决方案,ES6将其写进了语言标准,原生提供了Promise对象。
Promise主要解决了什么问题?
从零开始手写一个Promise
手写一个Promise需要遵循 Promise/A+规范
首先,我们从Promise最基础的概念开始:
pending
,fulfilled
,rejected
,状态只能从pending
到fulfilled
或rejected
,一旦确定无法改变;value
保存成功状态的值,一个reason
保存失败状态的值;executor
立即执行函数,函数接收resolve
和reject
两个函数参数. 若是executor
函数报错 直接执行reject()
;resolve()
将Promise状态变为fulfilled
,reject()
将Promise状态变为rejected
,并执行then()
传入的回调函数;then
函数, 依次传入onFulfilled
和onRejected
回调函数,当status为
fulfilled
时执行onFulfilled
回调函数,传入this.value。当status为rejected
时执行onRejected
函数,传入this.reason;按照上面的概念,我们可以写出一个最基本的Promise
写完代码测试一下
但这时候只是同步操作的Promise,若是我们在executor()中传入一个异步操作,则会什么都没有打印出来。
这是因为执行then方法时,此时Promise的状态是pending,不会触发回调。那么在pending状态的时候应该怎么做呢?
不考虑异常的情况下,Promise的状态改变只依赖于构造函数中的resolve()函数和reject函数,那么可以考虑将onFulfilled和onRejected回调函数先保存到Promise中我们定义的属性onFulfilledFn和onRejectedFn中,等到状态改变时再调用。
结合以上思路,优化一下代码:
此时测试一下,会发现浏览器延迟1s打印出‘success 成功’
then的链式调用
这是Promise实现的重点和难点,我们先来看一下JavaScript中原生Promise对象的then是如何链式调用的
这种链式调用该如何实现?
测试一下
这只是最简单的x值判断,只是单纯判断x是否Promise实例,实际上还需要判断更多复杂情况。所以我们可以优化一下,将判断x的函数命名为
resolvePromise
提取出来。resolvePromise
的参数有promise2(默认返回的promise)、x(我们自己return的对象)、resolve、reject。代码如下:
then的其它细节处理
这样,Promise的主要部分就完成了,完整代码如下:
写完代码测试一下
首先在Promise实现的代码中加入
安装测试脚本
在package.json中配置指令
promises-aplus-tests 中共有 872 条测试用例,代码完美通过

Promise 的 API
原生的Promise还提供了一些方法,我们顺便一起写出来
Promise.resolve()
Promise.reject()
Promise.prototype.catch()
Promise.prototype.finally()
Promise.all()
Promise.all 是解决并发问题的,多个异步并发获取最终的结果(如果有一个失败则失败)
Promise.race()
只需要一个Promise对象状态变为resolved或rejected时就调用then方法,它只会获取最先执行完成的那个结果。
Promise.allsettled()
allsettled()接受一组 Promise 实例作为参数,但和和.all()方法不同,只有等到所有这些参数实例都返回结果,不管是fulfilled还是rejected,包装实例才会结束。
Promise.any()
ES2021 引入了Promise.any()方法。该方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回。只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。
拓展
Promise是没有中断方法的,fetch是基于Promise的,所以它的请求无法中断,我们来实现一下Promise的中断。
abort写出来了,日常使用中,有些异步请求需要超时取消,我们可以根据abort,同理自定义超时。
好了,以上就是Promise的基本原理与实现了,希望你能从我的这篇博客中有所收获,谢谢。
代码仓库点击查看
The text was updated successfully, but these errors were encountered: