目录
Promise构造函数
then方法封装
catch方法封装
resolve方法封装
reject方法封装
all方法封装
race方法封装
这篇文章主要是介绍如何自己封装Promise构造函数以及其相应的方法。Promise是JS中的重点,很多的面试都会问到。因此需要对其有比较深入地认识。看这篇文章可能需要你对promise有一定的了解,不然可能会有点吃力。
Promise构造函数
首先需要知道Promise构造函数接受的参数,以及内部执行的逻辑功能。Promise构造函数接受一个函数作为实参。该函数具有两个参数,一个为resolve另一个为reject。当函数内部调用resolve函数是,代表promise实例的状态为fulfilled代表成功,同时可以将成功的值传给该函数。当函数内部调用reject函数时,就会让promise实例的状态为rejected代表失败,同时可以将失败的值传给该函数。
在该构造函数中需要声明resolve函数以及reject函数,resolve函数内部需要先判断实例对象的状态,只有当它的状态不为pending时,才能将该实例的状态变成fulfilled。这一步判断主要是解决实例的状态不能改变的情况,只能从pending到fulfilled或者是从pending到rejected。然后再将对应成功的值赋值该实例的PromiseResult属性。然后当实例的状态改变时它会执行对应then方法中的回调,该回调是在resolve函数中调用的。then方法为异步,因此需要加上该给定时器。同时当实例的状态改变时,该实例对应的多个then方法都会执行,因此可以声明一个用于存储回调函数的数组,然后遍历该数组除了对应的回调。reject函数是同个道理。
function Promise(executor){//添加属性this.PromiseState='pending';this.PromiseResult=null;//声明属性 存储回调函数this.callBacks=[];//保存实例对象的this值const self=this;//resolve函数function resolve(data){//判断状态if(self.PromiseState!=='pending') return;//修改对象的状态(promiseState)self.PromiseState='fulfilled';//设置对象结果值self.PromiseResult=data;//调用成功的回调函数setTimeout(()=>{self.callBacks.forEach(item=>{item.onResolved(data);})});}//reject函数function reject(data){//判断状态if(self.PromiseState!=='pending') return;//修改对象的状态(promiseState)self.PromiseState='rejected';//设置对象结果值self.PromiseResult=data;//调用失败的回调setTimeout(()=>{self.callBacks.forEach(item=>{item.onRejected(data);})});}try{//同步调用executor(resolve,reject);}catch(e){//修改promise对象状态为失败reject(e);}}
then方法封装
当promise实例状态发生改变时then方法会被调用。then方法传入两个参数,第一个参数是resolved
状态的回调函数,当实例的状态为成功时执行该函数。第二个参数是rejected
状态的回调函数,当实例的状态为失败时执行该函数。then方法返回的是一个新的Promise
实例。该实例对象的状态由回调函数的执行结果决定。如果回调函数中返回的结果是非promise类型的属性,状态为成功,返回的值为对象的成功的值。若没有return返回结果,则同样是成功的状态,只是对应的值为undefined。若返回的是一个promise对象,then返回的状态则为return中promise对象的状态,其值也是对应的内部return中promise的值。若是抛出错误,则then返回的promise对象的状态为失败的状态,对应的值为抛出的值。
then方法中的两个参数当第一个参数没有传入时,默认地给该参数设置为一个携带value参数并返回value的函数。这些做可以实现promise中对应的值传递的功能。当第二个参数没有传值时,我们默认的将该参数赋值为一个携带reason参数并返回reason的函数。这样可以实现promise中的异常穿透的功能。then方法的回调是异步执行的,因此需要在执行回调的时候包裹一个定时器。
当实例对象的状态还是pending时,将对应的回调存放到保存回调函数的数组中。当实例的状态改变时则会进行调用。
Promise.prototype.then=function(onResolved,onRejected){const self=this;//判断回调函数参数if(typeof onRejected !=='function'){onRejected=reason=>{throw reason;}}if(typeof onResolved !== 'function'){onResolved = value => value;}return new Promise((resolve,reject)=>{//封装函数function callback(type){try{//获取回调函数的执行结果let result=type(self.PromiseResult);//判断if(result instanceof Promise){//如果是Promise类型的对象result.then(v=>{resolve(v);},r=>{reject(r);})}else{resolve(result);}}catch(e){reject(e);}}if(this.PromiseState==='fulfilled'){setTimeout(()=>{callback(onResolved);})}if(this.PromiseState==='rejected'){setTimeout(()=>{callback(onRejected);})}if(this.PromiseState==='pending'){//保存回调函数this.callBacks.push({onResolved:function(){callback(onResolved);},onRejected:function(){callback(onRejected);}})}});}
catch方法封装
该方法用于处理当promise实例的状态为失败时的回调,相当于是then方法的第二个回调函数。
Promise.prototype.catch=function(onRejected){return this.then(undefined,onRejected);
}
resolve方法封装
该方法是Promise构造函数的方法,不是其实例对象的方法。其的作用是返回一个成功的promise对象。若传入的值不是promise,则一定返回成功的状态。当传入的值为Promise对象时,它的状态由传入的promise的状态决定。
Promise.resolve=function(value){//返回promise对象return new Promise((resolve,reject)=>{if(value instanceof Promise){value.then(v=>{resolve(v);},r=>{reject(r);})}else{//状态设置为成功resolve(value);}})
}
reject方法封装
该方法是Promise构造函数的方法。其的作用是返回一个失败的promise对象。不管传入的参数是什么,都是返回一个失败状态的promise对象。
Promise.reject=function(reason){return new Promise((resolve,reject)=>{reject(reason);})
}
all方法封装
该方法是Promise构造函数的方法。该方法接受多个promise实例。当接收的所有promise实例对象的状态都为成功时才会是成功的状态,返回的结构为所有对象的成功值,存储在数组中。但有其中的一个实例对象的状态为失败时,all方法返回的promise对象的状态会变成失败,且对应的值为其中传入失败的promise对象失败的值。
这里需要声明一个变量来进行记录,但执行成功的回调时就会增加一,当该数值与数组的长度一样时,说明所有的promise实例的状态都为成功。则让其调用成功的回调函数。由于返回的值是原本数组中实例存放的位置,因此需要 arr[i]=v;执行数组的对应下标,存放对应实例的值。
Promise.all=function(promises){return new Promise((resolve,reject)=>{//声明变量let count=0;let arr=[];//遍历for(let i=0;i<promises.length;i++){promises[i].then(v=>{count++;//将当前promise对象成功的结果存入到数组arr[i]=v;//判断if(count==promises.length){//修改状态resolve(arr);}},r=>{reject(r);});}})
}
race方法封装
该方法是Promise构造函数的方法。该方法同样接受多个promise对象。它返回的promise对象的状态以及值,由第一个最先改变状态的promise对象决定。
遍历数组之后,此时只需要有一个成功,则就调用成功的回调。
Promise.race=function(promises){return new Promise((resolve,reject)=>{for(let i=0;i<promises.length;i++){promises[i].then(v=>{//修改返回对象的状态为成功resolve(v);},r=>{//修改返回对象的状态为失败reject(r);})}})
}
class封装
最后将其封装到class中,让其更加地简洁。
class Promise {//构造函数constructor(executor) {//添加属性this.PromiseState = 'pending';this.PromiseResult = null;//声明属性 存储回调函数this.callBacks = [];//保存实例对象的this值const self = this;//resolve函数function resolve(data) {//判断状态if (self.PromiseState !== 'pending') return;//修改对象的状态(promiseState)self.PromiseState = 'fulfilled';//设置对象结果值self.PromiseResult = data;//调用成功的回调函数setTimeout(() => {self.callBacks.forEach(item => {item.onResolved(data);})});}//reject函数function reject(data) {//判断状态if (self.PromiseState !== 'pending') return;//修改对象的状态(promiseState)self.PromiseState = 'rejected';//设置对象结果值self.PromiseResult = data;//调用失败的回调setTimeout(() => {self.callBacks.forEach(item => {item.onRejected(data);})});}try {//同步调用executor(resolve, reject);} catch (e) {//修改promise对象状态为失败reject(e);}}//then方法then(onResolved, onRejected) {const self = this;//判断回调函数参数if (typeof onRejected !== 'function') {onRejected = reason => {throw reason;}}if (typeof onResolved !== 'function') {onResolved = value => value;}return new Promise((resolve, reject) => {//封装函数function callback(type) {try {//获取回调函数的执行结果let result = type(self.PromiseResult);//判断if (result instanceof Promise) {//如果是Promise类型的对象result.then(v => {resolve(v);}, r => {reject(r);})} else {resolve(result);}} catch (e) {reject(e);}}if (this.PromiseState === 'fulfilled') {setTimeout(() => {callback(onResolved);})}if (this.PromiseState === 'rejected') {setTimeout(() => {callback(onRejected);})}if (this.PromiseState === 'pending') {//保存回调函数this.callBacks.push({onResolved: function () {callback(onResolved);},onRejected: function () {callback(onRejected);}})}});}//catch方法catch(onRejected) {return this.then(undefined, onRejected);}//添加resolve方法static resolve(value) {//返回promise对象return new Promise((resolve, reject) => {if (value instanceof Promise) {value.then(v => {resolve(v);}, r => {reject(r);})} else {//状态设置为成功resolve(value);}})}//添加reject方法static reject(reason) {return new Promise((resolve, reject) => {reject(reason);})}//添加all方法static all(promises) {return new Promise((resolve, reject) => {//声明变量let count = 0;let arr = [];//遍历for (let i = 0; i < promises.length; i++) {promises[i].then(v => {count++;//将当前promise对象成功的结果存入到数组arr[i] = v;//判断if (count == promises.length) {//修改状态resolve(arr);}}, r => {reject(r);});}})}//添加race方法static race(promises) {return new Promise((resolve, reject) => {for (let i = 0; i < promises.length; i++) {promises[i].then(v => {//修改返回对象的状态为成功resolve(v);}, r => {//修改返回对象的状态为失败reject(r);})}})}}
好啦!本文就到这里了。拜拜~~