Promise自定义封装
目录
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);
})
}
})
}
}
好啦!本文就到这里了。拜拜~~