当前位置: 首页 > 后端技术 > Node.js

JS深挖:手撕Promise详解代码全攻略

时间:2023-04-03 20:36:57 Node.js

内容:1.newPromise()2.then()和链式调用3..resolve()和.reject()4..all()和.race()在撕毁Promise之前,我们必须了解Promise的特性。首先,Promise本质上是一个构造函数,通过它可以创建Promise对象实例,以满足异步编程的需要。本文中我们需要实现的Promise特性如下:1.newPromise((resolve,reject)=>{})是一个构造函数,我们首先需要实现的是它的基本结构,我们首先实现最基本的功能:1)status存储状态,value和error存储成功/失败状态的值2)resolve和reject方法改变状态3)然后方法在状态改变后实现回调classMyPromise{constructor(executor){this.status='待办的';这个值;//成功状态的值this.error;//失败状态的值this.resolveCallbacks=[];this.rejectedCallbacks=[];letresolve=(res)=>{}letreject=(err)=>{}executor(resolve,reject)}then(onFulfilled,onRejected){}catch(){}}补充resolve和reject以及thenandcatch1)then最基本的功能就是在状态改变后调用回调函数2)catch的本质是.thenclassMyPromise{constructor(executor){this.status='pending';这个值;//成功状态的值this.error;//失败状态的值this.resolveCallbacks=[];this.rejectedCallbacks=[];letresolve=(res)=>{//改变状态,执行回调if(this.status==='pending'){this.status='resolved';this.value=res;}}让reject=(err)=>{//改变状态,执行回调if(this.status==='pending'){this.status='rejected';this.error=错误;}}executor(resolve,reject)}then(onFulfilled,onRejected){//本质是如果当前状态是resolved或rejected,则执行相应的回调函数if(this.status==='resolved'){onFulfilled(这个值);}if(this.status==='rejected''){onRejected(this.error)}}catch(rejected){returnthis.then(null,rejected)}}这样我们就可以调用构造函数来实现最基本函数//成功2、.then()和链式调用上面then的写法有几个问题:1)异步函数中状态变化时,.then()的执行。所以需要加上setTimeout3).那么返回值必须是Promise对象,所以每次异步处理的结果都设置为x,需要根据x来判断返回的promise2的状态和值这里,resolvePromise引入方法判断返回的promise2的状态和值初步改进如下:MyPromise.then(onFulfilled,onRejected){//本质是如果当前状态是resolved或rejected,则执行相应的回调函数letpromise2;promise2=newMyPromise((resolve,reject)=>{if(this.status==='resolved'){setTimeout(()=>{letx=onFulfilled(this.value);resolvePromise(promise2,x,resolve,拒绝);})}if(this.status==='rejected'){setTimeout(()=>{letx=onRejected(this.error);resolvePromise(promise2,x,resolve,reject);})}if(this.status==='pending'){this.resolveCallbacks.push(()=>{setTimeout(()=>{letx=onFulfilled(this.value);resolvePromise(promise2,x,resolve,reject);})});this.rejectedCallbacks.push(()=>{setTimeout(()=>{letx=onRejected(this.error);resolvePromise(promise2,x,resolve,reject);})});}})返回promise2;resolvePromise函数的实现是Promise实现的核心,里面包含了几个重要的规则。简单总结:1)如果返回值x是一个值,则返回fulfilled状态的Promise,值为x2)如果返回值x是一个Promise对象,继续递归调用3)只有当返回valuex是一个处于拒绝状态的Promise对象,返回的Promise函数是失败状态reject(newTypeError('检测到promise的链接循环'));}//锁定以防止多次调用letcalled;//x不为null而x是一个对象或函数if(x!=null&&(typeofx==='object'||typeofx==='function')){try{//A+规定then方法声明then=xletthen=x.then;//如果then是一个函数,它默认为一个promiseif(typeofthen==='function'){//让then执行。第一个参数是this,后面是成功的回调和失败的回调callbackthen.call(x,y=>{//成功和失败只能调用一个if(called)return;called=true;//的结果resolve还是promise,然后继续递归执行resolvePromise(promise2,y,resolve,reject);},err=>{//成功和失败只能调用一个if(叫)返回;称为=真;reject(err);//失败则失败})}else{resolve(x);//直接成功就可以了}}catch(e){//如果(调用)return也是失败;称为=真;//如果takethen有错误,就不要继续执行reject(e);}}else{解决(x);}}然后实现需要在最后添加一些细节,比如如果传入的onFullfilled不是函数,则忽略onFullfilled,直接返回值;还有之前调用的resolve和reject添加到回调数组onFulfilled=typeofonFulfilled==='function'?onFulfilled:value=>value;onRejected=typeofonRejected==='function'?onRejected:错误=>错误;3..resolve()和.reject()Promise也可以直接调用resolve和reject方法,其实质就是newPromise然后改变状态MyPromise.resolve=(value)=>{returnnewMyPromise((resolve,reject)=>{resolve(value);})}MyPromise.reject=(value)=>{returnnewMyPromise((resolve,reject)=>{reject(value);})}4、.all()和.race()先说all()方法,其实质就是只有参数中的所有Promise对象都被fulfilled才返回一个值,有具有以下特点:Promise.all([promise1,promise2,...])1)只有数组中的所有promise对象都被resolved,才会resolve,并返回Promise对象,值为所有promise的成功值objects2)如果有一个Promise对象reject,则返回第一个reject的promise结果。3)参数的promise只需要是可迭代的对象即可。如果传递的对象不是Promise对象,可以直接返回原值。MyPromise.all=(promises)=>{//promises是数组if(!Array.isArray(promises)){throw('mustbeanarray')}letres=[]returnnewMyPromise((resolve,reject)=>{for(leti=0;i{res.push(r);if(res.length===promises.length){//全部成功returnresolve(res);}},error=>{returnreject(error);})}else{//notapromiseobject然后直接保存值res.push(promises[i]);if(res.length===promises.length){//全部成功returnresolve(res);}}}})}race()方法与all相反,只返回改变所有Promise对象状态的对象作为参数,其特点如下:Promise.race(promises)1)当数组中某个Promise的状态变为fulfilled/rejected,race返回那个Promise的状态和它的值2)直接将race的resolve注入到数组中每个对象的回调中MyPromise.race=(promises)=>{returnnewMyPromise((resolve,reject)=>{对于(让我=0;我<承诺.长度;i++){promises[i].then(resolve,reject);}})}所有Promise都已完成