Promise手写
这里是对Promise的一些基本功能进行手写,其中包含各种API的讲解和实现,从0开始构建一个完整的Promise,适合新手。
初始结构搭建
首先我们可以根据Promise的实际使用观察出,当我们需要创建一个Promise对象时,需要传递一个参数(resolve,reject)=>{}。
let p = new Promise((resolve,reject)=>{
reoslve('OK');
})
因此在我们声明自己的Promise函数时,需要传递一个executor形参,也就是执行器。
function Promise(executor){};
resolve和reject的实现
-
当我们的实参传递给执行器的时候,promise内部会同步调用函数 。
function Promise(executor){ executor(resolve,reject); } -
接下来让我们来声明一下
resolve和reject,通过对原对象观察可知,resolve接收了一个实参。则我们可以将它声明为一个函数并传递一个形参;reject也是同理。function Promise(executor){ //声明resolve function resolve(data){ } //声明reject function reject(data){ } //同步调用【执行器函数】 executor(resolve,reject); }
在这里说明一下,因为是自己手写Promise,所以的命名都是自己设定的。简单来讲就是说,你可以命名这个执行器函数为executor,也可以是a,b,c等等,只要保证调用不出错就可以了。除此之外,当我们未引入该手写promise文件时,new Promise是全局的promise。引入后便是自己手写文件中的promise,不会冲突。
-
下面来进行函数的代码实现。我们知道
resolve函数有两大主要功能:1)修改对象状态为fulfilled
2)是指对象的结果值
实际上这两个都是实例对象身上的属性,
promiseState和promiseResult因此需要先添加这两个属性并设置初始值。
reject也是同理。function Promise(executor){ //添加属性 this.PromiseState = "pending";//pending为未决定的promise状态 this.promiseResult = null; //保存实例对象的this值 const self = this; //声明resolve function resolve(data){ //1.修改对象状态 //这里不能直接使用this.promiseState的原因是resolve是直接调用的,在这里指向windows,因此需要先保存 this的值再使用,或者使用箭头函数。 self.PromiseState = 'fulfilled';//fulfilled表示成功的状态,和resolve一样 //2.设置对象结果值 self.PromiseResult = data; } //声明reject function reject(data){ //1.修改对象状态 self.PromiseState = 'rejected';//rejected表示失败的状态 //2.设置对象结果值 self.PromiseResult = data; } //同步调用【执行器函数】 executor(resolve,reject); }
throw抛出异常改变状态
我们知道,promise改变状态有三种办法,除了resolve和reject,还有throw抛出错误。这里我们使用tey{}catch{}方法。
先简单介绍一下这个方法
try{
function one()
}catch(e){
function two(e)
}
//如果throw 'OK',则执行two('OK');否则执行one()
当我们抛出错误时,promise状态会变成失败,且throw的实参会传递给reject。
function Promise(executor){
//添加属性
this.PromiseState = "pending";
this.promiseResult = null;
//保存实例对象的this值
const self = this;
//声明resolve
function resolve(data){
//1.修改对象状态
self.PromiseState = 'fulfilled';
//2.设置对象结果值
self.PromiseResult = data;
}
//声明reject
function reject(data){
//1.修改对象状态
self.PromiseState = 'rejected';
//2.设置对象结果值
self.PromiseResult = data;
}
//抛出异常
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
reject(e);
}
}
Promise对象状态只能改变一次
我们知道,promise对象的状态初始为pening且只能改变一次。因此我们需要接入一个判断,判断当前promise状态是否改变,也就是是否为初始值pending。
在这里为了优化代码,我们也可以设置“在resolve和reject中判断promise,当它的状态不为初始值时,直接返回,不再继续执行resolve或reject”
function Promise(executor){
//添加属性
this.PromiseState = "pending";
this.promiseResult = null;
//保存实例对象的this值
const self = this;
//声明resolve
function resolve(data){
//判断promise状态是否已改变
if(self.PromiseState !== "pending")
return;
//1.修改对象状态
self.PromiseState = 'fulfilled';
//2.设置对象结果值
self.PromiseResult = data;
}
//声明reject
function reject(data){
//判断promise状态是否已改变
if(self.PromiseState !== "pending")
return;
//1.修改对象状态
self.PromiseState = 'rejected';
//2.设置对象结果值
self.PromiseResult = data;
}
//抛出异常
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
reject(e);
}
}
以上基本就是promise的基本构造了,接下来我们将继续构建一些promise常用的API。
then方法执行回调
-
首先还是观察promise.then方法的使用情况。
p.then(value=>{ console.log(value); },reason=>{ console.warn(reason); })可以知道,then方法需要传递两个参数
(onResolved,onReject),其中onResolved函数是成功的 回调函数(value)=>{};onReject是失败的回调函数(reason)=>{}。则添加then方法
Promise.prototype.then = function(onResolved,onRejected){ }; -
判断回调哪个函数。
我们需要先知道promise的状态才能够知道需要执行
onResolved还是onRejected函数,因此在then方法中先增加一个判断状态。Promise.prototype.then = function(onResolved,onRejected){ //调用回调函数 //这里可以直接使用this.promiseState是因为then方法是被p调用的,而p是一个promise对象,因此 这里的this实际上指向的是p这个promise对象。 if(this.PromiseState === 'fulfilled'){ onResolved(); } if(this.PromiseState === 'rejected'){ onRejected(); } }; -
传递参数
我们观察到当调用
onResolved时实际上是传递了一个value值,同理onRejected传递了reason值,这两个值实际上保存在PromiseResult中,因此可以设置this.PromiseResult为这两个函数的形参。Promise.prototype.then = function(onResolved,onRejected){ //调用回调函数 if(this.PromiseState === 'fulfilled'){ onResolved(this.PromiseResult); } if(this.PromiseState === 'rejected'){ onRejected(this.PromiseResult); } };
在这里可以对自己写的做一下检查,查看最基本的resolve,reject,throw在then方法中是否能够输出result。
异步任务回调的执行
promise是支持异步使用的,我们可以添加一个定时器尝试一下。
let p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('OK');
//reject('error');
//throw 'error';
},1000)
})
p.then(value=>{
console.log(value);
},reason=>{
console.log(reason);
})
添加定时器后,我们就需要先调用then方法,后再改变对象状态。注意,这里只是调用then方法,由于函数状态未改变,因此不能直接执行回调。此时对象状态仍然是pending。因此我们需要判断当对象状态为pending时需要执行的操作。
那么我们分析可以知道,无论什么时候调用then方法,我们都需要在状态改变后才能执行回调。因此我们可以将调用回调函数写在改变状态函数之后。使其既可以“先改变状态再调用then”,也可以”先调用then再改变状态“两种操作。
由于回调函数和改变状态函数(resolve和reject)是两个不同函数内的函数,无法直接调用。但是他们作用于同一个对象身上,因此我们可以在这个对象身上添加一个callback属性保存这两个回调函数。这样resolve和reject就可以调用到对应的回调函数了。
function Promise(executor){
this.PromiseState = "pending";
this.promiseResult = null;
const self = this;
//添加保存回调函数的属性
this.callback = {};
function resolve(data){
if(self.PromiseState !== "pending")
return;
self.PromiseState = 'fulfilled';
self.PromiseResult = data;
//调用成功的回调函数
//调用方法:这里需要首先判断是先改变状态还是先调用then。判断方法就是看调用then方法时promise的状态是否改变,如果改变,则callback内为空,按照原本的设定执行;如果不改变,则callback内会存入onResolved和onRejected。因此在这里,可以通过检查callback内部是否存在这两个函数来判断执行状态。
if(self.callback.onResolved){
//这里的参数实际上就是resolve的参数,也就是PromiseResult。
self.callback.onResolved(data);
}
}
function reject(data){
if(self.PromiseState !== "pending")
return;
self.PromiseState = 'rejected';
self.PromiseResult = data;
//调用失败的回调函数
//调用方法同resolve
if(self.callback.onRejected){
self.callback.onRejected(data);
}
}
try{
executor(resolve,reject);
}catch(e){
reject(e);
}
}
Promise.prototype.then = function(onResolved,onRejected){
if(this.PromiseState === 'fulfilled'){
onResolved(this.PromiseResult);
}
if(this.PromiseState === 'rejected'){
onRejected(this.PromiseResult);
}
if(this.PromiseState === 'pending'){
//保存回调函数
this.callback = {
onResolved:onResolved,
onRejected:onRejected
}
}
};
上面代码较之前代码共修改了四 个地方:1.在对象添加callback属性。2.在then方法内保存回调函数。3.在resolve中添加成功回调函数的调用。4.在reject中添加失败回调函数的调用。
多个回调的实现
我们知道promise可以同时指定 多个回调。比如:
let p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('OK');
//reject('error');
//throw 'error';
},1000)
});
//指定回调-1
p.then(value=>{
console.log(value);
});
//指定回调-2
p.then(value=>{
alert(value);
});
//两个回调会同时执行。
然而在我们的代码中,因为存在定时器,所以当回调-1指定时,会在callback中保存一次回调函数;当指定回调-2时,又会保存一次,则回调-1就被覆盖了。
因此,我们可以将callback声明成为一个数组,用以储存不同回调。
function Promise(executor){
this.PromiseState = "pending";
this.promiseResult = null;
const self = this;
//添加保存回调函数的数组属性
this.callbacks = [];
function resolve(data){
if(self.PromiseState !== "pending")
return;
self.PromiseState = 'fulfilled';
self.PromiseResult = data;
//那么此时调用回调函数就不能直接调用callback了,而是遍历callbacks数组。
//此时也不需要再进行判断,因为如果数组为空,便不能执行回调。
/*if(self.callback.onResolved){
self.callback.onResolved(data);
}*/
//这里的item是callbacks数组的元素,每个item都是一个包含有onResolved和onRejected的对象。
self.callbacks.forEach(item =>{
item.onResolved(data);
})
}
function reject(data){
if(self.PromiseState !== "pending")
return;
self.PromiseState = 'rejected';
self.PromiseResult = data;
/*if(self.callback.onRejected){
self.callback.onRejected(data);
}*/
self.callbacks.forEach(item =>{
item.onRejected(data);
})
}
try{
executor(resolve,reject);
}catch(e){
reject(e);
}
}
Promise.prototype.then = function(onResolved,onRejected){
if(this.PromiseState === 'fulfilled'){
onResolved(this.PromiseResult);
}
if(this.PromiseState === 'rejected'){
onRejected(this.PromiseResult);
}
if(this.PromiseState === 'pending'){
//那么这里就是新的回调向数组后面添加
this.callbacks.push({
onResolved:onResolved,
onRejected:onRejected
})
}
};
此段代码较改进的地方有四个:1.将callback对象改为数组,其内部储存的每个元素为对象。2.在then方法中 将保存callback对象改为向callbacks数组中 添加对象元素。3.在resolve中修改判断和调用为遍历callbacks数组。4.reject同理。
修改then方法返回结果的实现
then方法的返回结果是一个promise对象,其状态由内部回调函数的执行结果决定。如果执行结果返回了一个非promise类型的结果 ,则then方法返回的promise状态为成功;如果执行结果返回的是一个promise类型的结果,则这个promise的状态会决定then方法返回的promise对象状态。
- 首先需要将then方法的返回结果设置成一个promise对象
- 获取回调函数的执行结果,判断其是否为promise类型
- 通过判断执行结果“是否为promise类型”和“如果是promise类型那么其状态”来改变then返回的promise的状态
- 除了resolve和reject,我们还需要考虑回调函数的执行结果如果是抛出异常,则then方法的结果就变成失败的状态
Promise.prototype.then = function(onResolved,onRejected){
//将then方法的返回值设置成为promise对象类型
return new Promise((resolve,reject)=>{
if(this.PromiseState === 'fulfilled'){
try{
//获取回调函数的执行结果
let result = onResolved(this.PromiseResult);
//判断
if(result instanceof Promise){
//如果是promise类型,则该result可以调用then方法,可以通过调用then方法来设置不同状态的promise对于then的返回值状态的影响
result.then(v =>{
//这里的resolve内部指向result,因此改变的是result的状态,也就是then方法返回的promise状态。
//成功的结果为v
resolve(v);
},r =>{
//失败的结果为r
reject(r);
})
}else{
//执行结果为非promise类型则then方法返回的promise状态变为成功,该promise的成功的值应该是回调函数执行的结果,也就是result
resolve(result);
}
}catch(e){
reject(e);
}
}
if(this.PromiseState === 'rejected'){
try{
//获取回调函数的值
let result = onRejected(this.PromiseResult);
//判断
if(result instanceof Promise){
result.then(v =>{
//成功的结果为v
resolve(v);
},r =>{
//失败的结果为r
reject(r);
})
}else{
resolve(result);
}
}catch(e){
reject(e);
}
}
if(this.PromiseState === 'pending'){
this.callbacks.push({
onResolved:onResolved,
onRejected:onRejected
})
}
})
};
这里需要注意的是,原始的promise的状态,并不影响其then结果返回的结果的状态和值。
下图很好地解释了这一整个流程。
以上结果都是建立在同步执行的状态下,那么接下来我们将完善异步修改then方法的返回值。
let p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('OK');
//reject('error');
//throw 'error';
},1000)
});
const res = p.then(value =>{
console.log(value);
},reason =>{
console.log(reason);
})
console.log(res);
内置的promise会先返回一个pending状态的res,一秒钟以后打印OK,且res状态变为fulfilled,res结果的值为undifined,因为在这里回调函数未返回任何东西。
然而我们手写的promise并不会在一秒后改变res的状态和结果的值 。因为我们在处理异步状态的执行时,并没有设置promise状态为pending时有关于res结果的操作。
-
为了便于 对
pending状态的promise进行操作,我们将以函数形式保存这个回调函数,便于对保存的回调函数进行操作更改const self = this; if(this.PromiseState === 'pending'){ this.callbacks.push({ //onResolved:onResolved, onResolved:function(){ //这里不使用this.PromiseResult是因为在这个函数中,this指向callbacks。 onResolved(self.PromiseResult); } onRejected:function(){ onRejected(self.PromiseResult); } }) } -
接下来就是在
onResolved和onRejected中对回调函数的执行结果进行判断,与同步操作一致。const self = this; if(this.PromiseState === 'pending'){ this.callbacks.push({ onResolve:function(){ try{ //获取回调函数执行结果 let result = onResolved(self.PromiseResult); //判断 if(result instanceof Promise){ result.then(v=>{ resolve(v); },r =>{ reject(r); }) }else{ resolve(result); } }catch(e){ reject(e); } } onRejected:function(){ try{ //获取回调函数执行结果 let result = onRejected(self.PromiseResult); //判断 if(result instanceof Promise){ result.then(v=>{ resolve(v); },r =>{ reject(r); }) }else{ resolve(result); } }catch(e){ reject(e); } } }) }到这里,有关于同步异步的then方法结果值的实现都已经完成了,但是我们注意到,有关于“判断回调函数执行结果并改变
res状态”的代码重复出现了很多次,因此,我们可以对这个该段代码进行封装。Promise.prototype.then = function(onResolve,onReject){ const self = this; return new Promise((resolve,reject) =>{ //封装函数 function callback(type){ try{ //获取回调函数的执行结果 //这里的type传递的是不同状态的promise会调用`onResolved`还是`onRejected` let result = type(self.PromiseResult); //判断 if(result instance Promise){ result.then(v =>{ resolve(v); },r =>{ reject(r); }) }else{ resolve(result); } }catch(e){ reject(e); } } //调用回调函数 if(this.PromiseState === 'fulfilled'){ callback(onResolved); }; if(this.PromiseState === 'rejected'){ callback(onRejected); }; if(this.PromiseState === 'pending'){ //保存回调函数 this.callbacks.push({ onResolved:function(){ callback(onResolved); }, onRejected:function(){ callback(onRejected); } }) } }) }
catch方法和异常穿透
catch是专门演示失败的回调函数,因此可以直接调用then方法,改变参数即可。
Promise.prototype.catch = function(onRejected){
return this.then(undifined,onRejected);
}
异常穿透是指在进行链式调用时,只需要在最后设置失败的结果。意思就是前面所有的失败异常都可以由最终一个catch来处理。
let p = new Promise((resolve,reject)=>{
reject('error');
})
p.then(value =>{
console.log(111);
}).then(value =>{
console.log(222);
}).then(value =>{
console.log(333);
}).catch(reason =>{
console.warn(reason);
})
然而在我们的代码中,因为没有传递reason的相关内容,所以会报错onRejected is not a function ,在第一个then方法中无法找到onRejected。
因此我们需要设置:当onRejected is not a function时,需要直接抛出错误,使当前then方法返回一个失败的promise对象,那么下面的then方法也是在接收失败的promise对象后再抛出错误,逐步返回失败的promise对象一直到最后的catch做出失败的回调执行。
Promise.prototype.then = function(onResolve,onReject){
const self = this;
//判断
//判断错误的回调函数是否存在,若不存在,则抛出错误,then返回一个失败的promise对象。
//这里其实是相当于在then方法中添加了一个reason=>{throw reason}的回调。
if(typeof onRejected !== 'function'){
onRejected = (reason) =>{
throw reason;
}
}
return new Promise((resolve,reject) =>{
})
}
除了失败对象的传递,异常穿透还可以进行成功的值的传递。意思就是,如果整个链式调用中没有错误,则原始的promise成功的结果会不断传递给then方法返回的成功的promise,成为他们的结果值。
和onRejected的报错一样,因此我们也可以通过相同的判断方式,为onResolved创建一个传递值的功能。
Promise.prototype.then = function(onResolve,onReject){
const self = this;
if(typeof onRejected !== 'function'){
onRejected = (reason) =>{
throw reason;
}
}
if(typeof onResolved !== 'function'){
//这里相当于为onResolved添加了value =>{return value},将当前peomise的结果的值传递给then方法返回的promise。
onResolved = (value) => value;
}
return new Promise((resolve,reject) =>{
})
}
resolve的封装
接下来我们会封装一些promise的API.
首先是封装Promise.resolve。
我们先分析一下这个API的作用。他会传递一个value的值,这个值是promise成功的数据或者一个promise对象。且该API会返回一个promise对象
- 如果传入的参数是非promise类型的对象,则返回的结果为成功的promise对象。
- 如果传入的参数为promise对象,则参数的结果决定了resolve的结果。
Promise.resolve = function(value){
return new Promise((resolve,reject)=>{
if(value instanceof Promise){
value.then(v=>{
resolve(v);
},r=>{
reject(r);
})
}else{
resolve(value);
}
})
}
与then方法的callback封装类似。
reject的封装
Promise.reject方法接收一个reason参数,返回一个失败的promise对象。不管传入什么都失败;传入什么,失败的结果就是什么;
Promise.reject(reason){
return new Promise((resolve,reject) =>{
reject(reason);
})
}
all方法的封装
all方法会传入一个包含有n个promise对象的数组的参数,返回一个新的promise对象。当数组中的所有promise对象都成功时,返回的结果状态为成功,成功的结果为一个包含有所有promise成功值的数组;如果有失败的promise对象,则返回结果也为失败,且失败的值为第一个改变状态的promise的值。
Promise.all = function(promises){
return new Promise((resolve,reject) =>{
//因为所有的promise状态为成功,返回的结果状态才能改变为成功,所以需要设置一个值来检查数组中成功状态的promise是否符合要求。
let count = 0;
//设置一个数组来保存成功的promise的值
let arr[];
//遍历
for(let i = 0;i < promises.length;i++){
promises[i].then(v =>{
count++;
arr[i] = v;
//判断
if(count === promises.length){
//修改成功状态
resolve(arr);
}
},reason =>{
//如果有失败的,则立即返回当前失败的值
reject(r);
})
}
})
}
race方法的封装
race方法会接收一个包含有n个promise对象的数组,,返回一个新的promise,第一个完成状态改变的结果就是返回的结果。
Promise.race = function(promises){
return new Promise((resolve,reject) =>{
for(let i = 0; i < promises.length;i++){
//当前promise状态改变后便立即返回结果。
promises[i].then(v =>{
resolve(v);
},reason =>{
reject(r);
})
}
})
}
回调函数异步执行
promise中有一个细节就是then方法中的回调函数实际上是异步执行的。
我们可以做一个检测。
let p = new Promise((resolve,reject)=>{
resolve('OK');
console.log(111);
})
p.then(value =>{
console.log(222);
})
console.log(333);
//输出顺序为111,333,222
所以可以验证,then中的回调函数是异步执行的,需要等同步代码执行结束才能运行。
因此我们需要在手写的then方法中的回调函数内部添加内容使其变为异步。目前代码中总共有四处回调函数需要修改。
//声明构造函数
function Promise(executor) {
this.PromiseState = "pending";
this.PromiseResult = null;
this.callbacks = [];
const self = this;
//resolve函数
function resolve(data) {
if (self.PromiseState !== "pending") return;
self.PromiseState = "fulfilled";
self.PromiseResult = data;
//添加定时器设置成为异步任务
setTimeout(() => {
self.callbacks.forEach((item) => {
item.onResolved(data);
});
});
}
//reject函数
function reject(data) {
if (self.PromiseState !== "pending") return;
self.PromiseState = "rejected";
self.PromiseResult = data;
//定时器包裹成为异步任务
setTimeout(() => {
self.callbacks.forEach((item) => {
item.onRejected(data);
});
});
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
//添加then方法,返回结果为promise对象
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) {
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);
},
});
}
});
};
总结
到这里,promise的手写便基本完成了。下面是整体的代码以及一些注解。
//声明构造函数
function Promise(executor) {
//添加属性
this.PromiseState = "pending";
this.PromiseResult = null;
//声明属性
this.callbacks = [];
//保存实例对象的this值
const self = this; //self _this that
//resolve函数
function resolve(data) {
//判断
if (self.PromiseState !== "pending") return;
//1.修改对象状态(promiseState)
self.PromiseState = "fulfilled";
//2.设置对象结果值(promiseResult)
self.PromiseResult = data;
//调用成功的回调函数
setTimeout(() => {
self.callbacks.forEach((item) => {
item.onResolved(data);
});
});
}
//reject函数
function reject(data) {
if (self.PromiseState !== "pending") return;
//1.修改对象状态(promiseState)
self.PromiseState = "rejected";
//2.设置对象结果值(promiseResult)
self.PromiseResult = data;
//调用失败的回调函数
setTimeout(() => {
self.callbacks.forEach((item) => {
item.onRejected(data);
});
});
}
try {
//同步调用【执行器函数】
executor(resolve, reject);
} catch (e) {
//修改promise对象状态为【失败】
reject(e);
}
}
//添加then方法,返回结果为promise对象
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);
}
}
//调用回调函数 PromiseState
//this指向实例对象p
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.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected);
};
//resolve方法
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.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
};
//all方法
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) => {
//得知对象状态都是成功
//每个promise对象都成功
count++;
///当前promise对象成功的结果存入数组
arr[i] = v;
//判断
if (count === promises.length) {
//修改状态
resolve(arr);
}
},
(r) => {
reject(r);
}
);
}
});
};
//race方法
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);
}
);
}
});
};
该篇文章记录尚硅谷Promise教程,有兴趣的同学可以深入学习一下尚硅谷Web前端Promise教程从入门到精通_哔哩哔哩_bilibili