promise的特点,参考阮一峰ES6
- Promise是一个构造函数,构造函数接收一个函数类型的参数
- promise最后只能有一种状态,并且状态不能改变
- promise构造函数的原型链上存在then catch方法,then/catch方法也返回promise
- promise支持异步执行
- promise支持链式调用
- promise.all
- promise.race
废话不多说,那我们下面就开始“搞事情”吧!
实现promise的第一步:做一些准备工作
- 我需要一个构造函数
Promise本身就是一个构造函数。
function MyPromise() {
}
MyPromise.prototype.then = function () { }
MyPromise.prototype.catch = function () { }
MyPromise.prototype.all = function () { }
MyPromise.prototype.race= function () { }
- 准备一些“状态机”变量
promise有三种状态,一个promise必然会处在三个状态中的某一个状态里面
- 待定(pending) : 初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled) : 意味着操作成功完成。
- 已拒绝(rejected) : 意味着操作失败。 下面第一个status变量来存储当前状态,定义success来表示成功状态下的值,error来表失败状态下的值。
function MyPromise() {
this.status = 'pending';//初始状态
this.success = undefined;
this.error = undefined;
}
MyPromise.prototype.then = function () { }
实现Promise的第二步:实现then函数。
这一步Promise的函数类型的参数可以起作用了,回调函数可以接收两个参数(resolve,reject),最后执行回调函数,在then函数中可以接收此时Promise的值
1. 将promise的值传给then函数
function MyPromise(executor) {
this.status = 'pending';//初始状态
this.success = undefined;
this.error = undefined;
let that = this;
function resolve(val) {
that.status = 'fufilled';
that.success = val;//保存当前成功的返回值
}
function reject(val) {
that.status = 'rejected'
that.error = val;
}
executor(resolve, reject);
}
2. 让then函数来接收Promise执行后返回的值
MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
handleFulfilled(this.success);//成功的值
handleRejected(this.error);//失败的值
}
3. new一个实例看看
- 用我们写的MyPromise来new一个实例
function MyPromise(executor) {
this.status = 'pending';//初始状态
this.success = undefined;
this.error = undefined;
let that = this;
function resolve(val) {
that.status = 'fufilled';
that.success = val;//保存当前成功的返回值
}
function reject(val) {
that.status = 'rejected'
that.error = val;
}
executor(resolve, reject);
}
MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
handleFulfilled(this.success);//成功的值
handleRejected(this.error);//失败的值
}
let mypromise = new MyPromise((resolve, reject) => {
resolve('success');
reject('reject');
})
mypromise.then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
输出的结果如下:
不对丫,不是说promise只能有一种状态的都嘛,那现在?
- 看看Promise new出来的实例呢
let promise = new Promise((resolve, reject) => {
resolve('success');
reject('reject');
})
promise.then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
输出的结果如下:
诺,只输出了一种状态,再将我们的promise改吧改吧。
实现promise的第三步:让promise的状态只能有一个
我们只允许promise的状态从pending=>fufilled或者pending=>rejected,所以,在then函数中加了一次判断。
function MyPromise(executor) {
this.status = 'pending';//初始状态
this.success = undefined;
this.error = undefined;
let that = this;
function resolve(val) {
if (that.status == "pending") {
that.status = 'fufilled';
that.success = val;//保存当前成功的返回值
}
}
function reject(val) {
if (that.status == "pending") {
that.status = 'rejected'
that.error = val;
}
}
executor(resolve, reject);
}
MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
let that = this;
debugger
//根据当前的状态,执行对应的状态处理函数
if (that.status == 'fufilled') {
handleFulfilled(this.success);//成功的值
}
if (that.status == 'rejected') {
handleRejected(this.error);//失败的值
}
}
let mypromise = new MyPromise((resolve, reject) => {
resolve("success");
reject("error");
})
mypromise.then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
再试试呢?只输出了一个值,现在状态总算是对了。
实现promise的第四步:异步呀异步,关键是要让promise函数执行异步丫
看看Promise函数是怎么处理的
这里我们用setTimeout函数来模拟异步
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("success");
reject("error");
}, 2000)
})
promise.then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
运行上面的代码,2s后会输出一个状态:success,这里先执行的resolve,执行之后状态不会改变。
试试我们的mypromise呢
function MyPromise(executor) {
this.status = 'pending';//初始状态
this.success = undefined;
this.error = undefined;
let that = this;
function resolve(val) {
if (that.status == "pending") {
that.status = 'fufilled';
that.success = val;//保存当前成功的返回值
}
}
function reject(val) {
if (that.status == "pending") {
that.status = 'rejected'
that.error = val;
}
}
executor(resolve, reject);
}
MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
let that = this;
if (that.status == 'fufilled') {
handleFulfilled(this.success);//成功的值
}
if (that.status == 'rejected') {
handleRejected(this.error);//失败的值
}
}
let mypromise = new MyPromise((resolve, reject) => {
setTimeout(() => {//模拟异步
resolve("success");
reject("error");
}, 2000)
})
mypromise.then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
好了,执行!!我等鸭等等了2s,哎不止2s,依然啥都没有输出。 我们来分析一哈,这个是爪子回事嘛
- 第一步:执行new Promise里面的内容
- 第二步:执行到executor(resolve, reject);
- 第三步:遇到setTimeout标记为宏2任务,等待。
- 第四步:执行then函数 ,但是status状态为pending,handleFulfilled, handleRejected此时没有被执行
- 第四步:2s到了,开始执行Promise里面的resolve函数,resolve函数执行完了,给status/success/error赋值
关键的问题是:遇到异步问题的时候,我们不想让then里面的handleFulfilled, handleRejected函数那么快执行。 使用两个变量,当执行到then的时候,如果状态为pending将handleFulfilled, handleRejected参数存下来,等到2s之后调用resolve函数的时候,再调用handleFulfilled处理接收值。
function MyPromise(executor) {
this.status = 'pending';//初始状态
this.success = undefined;
this.error = undefined;
let that = this;
that.onfufilledCallback = null;
that.onrejectedCallback = null;
function resolve(val) {
debugger
if (that.status == "pending") {
that.status = 'fufilled';
that.success = val;//保存当前成功的返回值
that.onfufilledCallback(that.success);
}
}
function reject(val) {
if (that.status == "pending") {
that.status = 'rejected'
that.error = val;
that.onrejectedCallback(that.error);//同步执行的时候缓存
}
}
executor(resolve, reject);
}
MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
let that = this;
if (that.status == 'fufilled') {
handleFulfilled(this.success);//成功的值
}
if (that.status == 'rejected') {
handleRejected(this.error);//失败的值
}
if (that.status == 'pending') {
that.onfufilledCallback = handleFulfilled//将处理函数存下来
that.onrejectedCallback = handleRejected//将处理函数存下来
}
}
let mypromise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve("success"); //执行Promise里面的resolve函数的时候,会在执行that.onfufilledCallback ,相当于执行then的handleFulfilled方法
reject("error");
}, 2000)
})
mypromise.then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
2s后成功输出:success 梳理一下执行过程
- 第一步执行new Promise里面的内容
- 第二步执行executor(resolve, reject),执行executor的时候遇到setTimeout将setTimeout标记为宏任务,入栈;
- 执行then then里面的函数为status为pending 将handleFulfilled函数缓存
- 执行setTimeout里面的resolve 此时的状态是pending
- 执行then中的缓存函数--->that.onfufilledCallback()
实现promise的第五步:说好的promise支持经典的链式调用呢
看看Promise
第二个then函数接收到了第一个then函数return出去的值
- 执行resolve
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("success");
}, 2000)
})
promise.then((res) => {
console.log(res)
return 1
}, (err) => {
console.log(err)
}).then(res => {
console.log(res)
})
- 执行reject
所以不管上一个then走的是resolve还是reject状态,第二个then函数都可以接收到第一个then的返回值 用我们第四步的MyPromise去执行上面相同的代码呢
let mypromise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve("success"); //执行Promise里面的resolve函数的时候,会在执行that.onfufilledCallback ,相当于执行then的handleFulfilled方法
reject("error");
}, 2000)
})
mypromise.then((res) => {
console.log(res)
return 1
}, (err) => {
console.log(err)
}).then(res => {
console.log(res)
})
好家伙,直接报错,嗯,不用想肯定也会报错,我们的then函数返回的也根本不是promise哇
让我们的MyPromise也支持链式调用 怎么办?那还不简单,让我们的then函数返回一个promise不就行了?
- 将我们的MyPromise.prototype.then函数直接返回一个promise
function MyPromise(executor) {
this.status = 'pending';//初始状态
this.success = undefined;
this.error = undefined;
let that = this;
that.onfufilledCallback = [];
that.onrejectedCallback = [];
function resolve(val) {
if (that.status == "pending") {
that.status = 'fufilled';
that.success = val;//保存当前成功的返回值
that.onfufilledCallback(that.success);
}
}
function reject(val) {
if (that.status == "pending") {
that.status = 'rejected'
that.error = val;
that.onrejectedCallback(that.error);//同步执行的时候缓存
}
}
executor(resolve, reject);
}
MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
let that = this;
let mypromise2 = new MyPromise((resolve, reject) => {
if (that.status == 'fufilled') {
try {
let res = handleFulfilled(this.success);//成功的值
resolve(res);
} catch (e) {
reject(e)
}
}
if (that.status == 'rejected') {
try {
let err = handleRejected(this.error);//失败的值
resolve(err);
} catch (e) {
reject(e)
}
}
if (that.status == 'pending') {
that.onfufilledCallback = handleFulfilled//将处理函数存下来
that.onrejectedCallback = handleRejected//将处理函数存下来
}
})
return mypromise2
}
let mypromise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve("success"); //执行Promise里面的resolve函数的时候,会在执行that.onfufilledCallback ,相当于执行then的handleFulfilled方法
reject("error");
}, 2000)
})
mypromise.then((res) => {
console.log(res)
return 1
}, (err) => {
console.log(err)
}).then(res => {
console.log(res)
})
执行输出:现在是不报错了,但是第二个then函数根本也没有执行
- 按照第二步的思路,我们有一个then函数就会缓存这个then函数的handleFulfilled,然后等2s之后执行这个handleFulfilled,那么有多个then的时候是不是也需要缓存多个then的handleFulfilled,然后等2s之后将所有的依次执行
function MyPromise(executor) {
this.status = 'pending';//初始状态
this.success = undefined;
this.error = undefined;
let that = this;
that.onfufilledCallback = [];
that.onrejectedCallback = [];
function resolve(val) {
if (that.status == "pending") {
that.status = 'fufilled';
that.success = val;//保存当前成功的返回值
that.onfufilledCallback.forEach(resolvefn => {
resolvefn(that.success);
});
}
}
function reject(val) {
if (that.status == "pending") {
that.status = 'rejected'
that.error = val;
that.onrejectedCallback.forEach(rejectfn => {
rejectfn(that.error);
});//同步执行的时候缓存
}
}
executor(resolve, reject);
}
MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
let that = this;
let mypromise2 = new MyPromise((resolve, reject) => {
debugger
if (that.status == 'fufilled') {
try {
let res = handleFulfilled(this.success);//成功的值
resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
}
if (that.status == 'rejected') {
try {
let err = handleRejected(this.error);//失败的值
resolve(err);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
}
if (that.status == 'pending') {
//当函数调用的时候,去执行数组里面的函数
that.onfufilledCallback.push(() => {
try {
let res = handleFulfilled(this.success)
resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
});//这里的onfufulled就相当于then里面的第一个参数回调
that.onrejectedCallback.push(() => {
try {
let res = handleRejected(this.error);
resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
});
}
})
return mypromise2
}
let mypromise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve("success"); //执行Promise里面的resolve函数的时候,会在执行that.onfufilledCallback ,相当于执行then的handleFulfilled方法
reject("error");
}, 2000)
})
mypromise.then((res) => {
console.log(res)
return 1
}, (err) => {
console.log(err)
}).then(res => {
console.log(res)
})
看看输出:
多调用几次then呢
发生了什么,怎么一下子就对了,那我们来分析一下上面的代码都干了啥吧
- 第一步:依然是执行new Promise中的同步代码,我们加了两个数组 that.onfufilledCallback = [];that.onrejectedCallback = [];来缓存then函数的handleFulfilled方法, handleRejected方法
- 第二步:执行 executor(resolve, reject);的时候遇到setTimeout,那就先等等再来执行setTimeout里面的东西吧
- 第三步:执行第一个then吧
- 第四步:在then函数里面有new MyPromise执行吧
- 第五步:执行then函数中的executor(resolve, reject),同步执行当前的状态是pending,并且将当前handleFulfilled, handleRejected缓存了下来
- 第六步:执行第二个then函数,操作过程同上一个then,依次将第二个then的handleFulfilled缓存下来
- 第七步:第三个then执行,缓存
- 第八步:终于轮到setTimeout函数执行了,执行resolve然后将上面缓存的三个then函数里面的全部执行 总结这一步的关键点
- 定义缓存数组
- 执行resolve的时候将缓存数组里的函数依次执行
实现promise的第六步,那么catch函数也得会嘛
与then函数不同的是catch函数只接受一个参数,执行catch函数相当于走then函数的第二个参数函数
MyPromise.prototype.catch = function (callback) {
return this.then(function () { }, callback)
}
let mypromise = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject("error");
}, 2000)
})
mypromise.catch(err => {
console.log(err)
})
输出:error
实现promise的第七步:也得让我们的MyPromise支持promise.all嘛
先看看Promise.all的用法吧
- 我传入一个普通的数组:输出[1,2]
Promise.all([1, 2]).then(res => {
console.log(res)
})
- 传入异步函数数组:输出:[promise1,promise2]
let promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise1');
}, 2000)
})
let promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise2');
}, 2000)
})
Promise.all([promise1, promise2]).then(res => {
console.log(res)
})
如果传入的是普通数组,传入啥就返回啥,如果是promise数组,执行每个promise,将结果返回,当我们都执行完数组里面的函数的时候,需要resolve
MyPromise.prototype.all = function (values) {
return new Promise(function (resolve, reject) {
let num = 0;
let arr = [];
for (let i = 0; i < values.length; i++) {
let current = values[i];
if (current.then && typeof current.then == "function") {
//此时是promise对象
current.then.call(current, function (val) { //此时是执行完的结果
arr[i] = val
if (++num == values.length) {
resolve(arr)
}
}, reject)
} else {
//说明是具体的值
arr[i] = current
if (++num == values.length) {
resolve(arr)
}
}
}
})
}
实现promise的第八步,顺便把race也实现了吧
MyPromise.prototype.race = function (values) {
return new Promise(function (resolve, reject) {
try {
let num = 0;
let arr = [];
let current
for (let i = 0; i < values.length; i++) {
current = values[i]
if (current.then && typeof current.then == "function") {
current.then(resolve, reject)
} else {
resolve(current)
}
}
} catch (e) {
reject(e)
}
})
}
总结一下吧
- 第一步的时候做了一些准备工作
- 第二步实现了then函数,利用回调函数,分别处理了成功的值和失败的值
- 第三步:promise的状态只能有一个,用了status来判断当前应该走哪一个处理函数
- 第四步:让promise支持异步调用,关键点就是缓存then函数,等同步函数执行完之后,再执行then里面的函数。
- 第五步:链式调用,链式调用关键一步是让then函数也返回一个promise,同时要要缓存多个then函数的处理函数,等到同步执行完之后,依次执行then函数里面的处理函数。
- 第六步里面的catch,和then函数的区别:catch相当于then函数中走的第二个reject回调
- 第七步:promise all :分为promise数组和普通数组,普通数组直接输出,promise数组依次执行,当数组里面的promise都执行完之后,输出执行后的值
- 第八步:race比promise.all更简单,执行完一个得到一个状态就输出
查漏补缺
上面粗略的实现了promise以及几个常用的方法,但是还有很多细节的地方没有处理好。这一篇继续查漏补缺,继续看下去吧
解决上一篇的promise会阻塞同步任务的问题
- 利用Promise函数实现如下代码
let promise = new Promise((resolve, reject) => {
resolve('data')
})
promise.then(res => {
console.log(res)
})
console.log('end')
输出:
- 用上一篇的MyPromise函数执行和上面相同的代码
let promise = new MyPromise((resolve, reject) => {
resolve('data')
})
promise.then(res => {
console.log(res)
})
console.log('end')
输出:
我们都知道promise.then是微任务,执行上面代码的时候先将整个代码作为宏任务开始执行,依次执行new Promise-->遇到promise.then放进微任务队列--->继续执行同步console.log("end")--->本次的宏任务执行完之后执行promise.then微任务,所以应该先输出end.
- 解决方法:将promise.then(handleFulfilled, handleRejected),handleFulfilled和handleRejected调用的时候处理成异步任务。 这里先用setTimeout来模拟一下异步任务,比较方便。其实我们都知道promise.then是微任务,
function MyPromise(executor) {
this.status = 'pending';//初始状态
this.success = undefined;
this.error = undefined;
let that = this;
that.onfufilledCallback = [];
that.onrejectedCallback = [];
function resolve(val) {
setTimeout(() => {
if (that.status == "pending") {
that.status = 'fufilled';
that.success = val;//保存当前成功的返回值
that.onfufilledCallback.forEach(resolvefn => {
resolvefn(that.success);
});
}
})
}
function reject(val) {
setTimeout(() => {
if (that.status == "pending") {
that.status = 'rejected'
that.error = val;
that.onrejectedCallback.forEach(rejectfn => {
rejectfn(that.error);
});//同步执行的时候缓存
}
})
}
executor(resolve, reject);
}
在执行上面的代码输出:
new Promise((resolve,reject)=>{resolve(p1)}) resolve(p1)p1可以是一个promise对象
- 利用Promise函数实现下面的代码
let promise = new Promise((resolve, reject) => {
let p = new Promise((resolve2, reject2) => {
resolve2('p222')
})
resolve(p)
})
promise.then(res => {
console.log(res)
})
console.log('end')
输出如下:resolve(p2),p2是一个promise也会帮我们执行并输出
- 看看MyPromise代码执行的结果
let promise = new MyPromise((resolve, reject) => {
let p = new MyPromise((resolve2, reject2) => {
resolve2('p222')
})
resolve(p)
})
promise.then(res => {
console.log(res)
})
console.log('end')
输出的结果如下:
- 解决方法,resolve函数里面判断是不是promise,如果是手动执行一次
function MyPromise(executor) {
this.status = 'pending';//初始状态
this.success = undefined;
this.error = undefined;
let that = this;
that.onfufilledCallback = [];
that.onrejectedCallback = [];
function resolve(val) {
if (val instanceof MyPromise) {
return val.then(resolve, reject)
}
setTimeout(() => {
if (that.status == "pending") {
that.status = 'fufilled';
that.success = val;//保存当前成功的返回值
that.onfufilledCallback.forEach(resolvefn => {
resolvefn(that.success);
});
}
})
}
function reject(val) {
setTimeout(() => {
if (that.status == "pending") {
that.status = 'rejected'
that.error = val;
that.onrejectedCallback.forEach(rejectfn => {
rejectfn(that.error);
});//同步执行的时候缓存
}
})
}
executor(resolve, reject);
}
Promise穿透实现
- 先用promise执行下面的代码
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p1')
}, 2000)
})
promise.then(null).then(res => {
console.log(res)
})
输出:
- 利用MyPromise执行上面同样代码
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p1')
}, 2000)
})
promise.then(null).then(res => {
console.log(res)
})
输出结果:没有任何输出
- 这其实是promise穿透现象:给then传递非函数值作为参数的时候,实际上会被解析成then(null).上一个Promise对象的执行结果会穿透到下一个then方法参数中= 在then函数里面处理一下,如果传入的不是函数,就将当前的参数包裹为一个函数 将then函数改造成如下:
MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
handleFulfilled = typeof handleFulfilled == 'function' ? handleFulfilled : (data) => { return data }
handleRejected = typeof handleRejected == 'function' ? handleRejected : (data) => { return data }
let that = this;
let mypromise2 = new MyPromise((resolve, reject) => {
if (that.status == 'fufilled') {
try {
let res = handleFulfilled(this.success);//成功的值
resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
}
if (that.status == 'rejected') {
try {
let err = handleRejected(this.error);//失败的值
resolve(err);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
}
if (that.status == 'pending') {
//当函数调用的时候,去执行数组里面的函数
that.onfufilledCallback.push(() => {
try {
let res = handleFulfilled(this.success)
resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
});//这里的onfufulled就相当于then里面的第一个参数回调
that.onrejectedCallback.push(() => {
try {
let res = handleRejected(this.error);
resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
});
}
})
return mypromise2
}
附上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
function MyPromise(executor) {
this.status = 'pending';//初始状态
this.success = undefined;
this.error = undefined;
let that = this;
that.onfufilledCallback = [];
that.onrejectedCallback = [];
function resolve(val) {
if (that.status == "pending") {
that.status = 'fufilled';
that.success = val;//保存当前成功的返回值
that.onfufilledCallback.forEach(resolvefn => {
resolvefn(that.success);
});
}
}
function reject(val) {
if (that.status == "pending") {
that.status = 'rejected'
that.error = val;
that.onrejectedCallback.forEach(rejectfn => {
rejectfn(that.error);
});//同步执行的时候缓存
}
}
executor(resolve, reject);
}
MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
let that = this;
let mypromise2 = new MyPromise((resolve, reject) => {
if (that.status == 'fufilled') {
try {
let res = handleFulfilled(this.success);//成功的值
resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
}
if (that.status == 'rejected') {
try {
let err = handleRejected(this.error);//失败的值
resolve(err);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
}
if (that.status == 'pending') {
//当函数调用的时候,去执行数组里面的函数
that.onfufilledCallback.push(() => {
try {
let res = handleFulfilled(this.success)
resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
});//这里的onfufulled就相当于then里面的第一个参数回调
that.onrejectedCallback.push(() => {
try {
let res = handleRejected(this.error);
resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
});
}
})
return mypromise2
}
MyPromise.prototype.catch = function (callback) {
return this.then(function () { }, callback)
}
MyPromise.prototype.all = function (values) {
return new Promise(function (resolve, reject) {
let num = 0;
let arr = [];
for (let i = 0; i < values.length; i++) {
let current = values[i];
if (current.then && typeof current.then == "function") {
//此时是promise对象
current.then.call(current, function (val) { //此时是执行完的结果
arr[i] = val
if (++num == values.length) {
resolve(arr)
}
}, reject)
} else {
//说明是具体的值
arr[i] = current
if (++num == values.length) {
resolve(arr)
}
}
}
})
}
MyPromise.prototype.race = function (values) {
return new Promise(function (resolve, reject) {
try {
let num = 0;
let arr = [];
let current
for (let i = 0; i < values.length; i++) {
current = values[i]
if (current.then && typeof current.then == "function") {
current.then(resolve, reject)
} else {
resolve(current)
}
}
} catch (e) {
reject(e)
}
})
}
let mypromise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve("success"); //执行Promise里面的resolve函数的时候,会在执行that.onfufilledCallback ,相当于执行then的handleFulfilled方法
reject("error");
}, 2000)
})
mypromise.race([mypromise]).then(res => {
console.log(res, "resssssssssss")
}).catch(e => {
console.log(e)
})
</script>
</body>
</html>
完整代码(完善了一些细节)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
function MyPromise(executor) {
this.status = 'pending';//初始状态
this.success = undefined;
this.error = undefined;
let that = this;
that.onfufilledCallback = [];
that.onrejectedCallback = [];
function resolve(val) {
if (val instanceof MyPromise) {
return val.then(resolve, reject)
}
setTimeout(() => {
if (that.status == "pending") {
that.status = 'fufilled';
that.success = val;//保存当前成功的返回值
that.onfufilledCallback.forEach(resolvefn => {
resolvefn(that.success);
});
}
})
}
function reject(val) {
setTimeout(() => {
if (that.status == "pending") {
that.status = 'rejected'
that.error = val;
that.onrejectedCallback.forEach(rejectfn => {
rejectfn(that.error);
});//同步执行的时候缓存
}
})
}
executor(resolve, reject);
}
MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
handleFulfilled = typeof handleFulfilled=='function'?handleFulfilled:(data)=>{return data}
handleRejected = typeof handleRejected=='function'?handleRejected:(data)=>{return data}
let that = this;
let mypromise2 = new MyPromise((resolve, reject) => {
if (that.status == 'fufilled') {
try {
let res = handleFulfilled(this.success);//成功的值
resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
}
if (that.status == 'rejected') {
try {
let err = handleRejected(this.error);//失败的值
resolve(err);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
}
if (that.status == 'pending') {
//当函数调用的时候,去执行数组里面的函数
that.onfufilledCallback.push(() => {
try {
let res = handleFulfilled(this.success)
resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
});//这里的onfufulled就相当于then里面的第一个参数回调
that.onrejectedCallback.push(() => {
try {
let res = handleRejected(this.error);
resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
} catch (e) {
reject(e)
}
});
}
})
return mypromise2
}
MyPromise.prototype.catch = function (callback) {
return this.then(function () { }, callback)
}
MyPromise.prototype.all = function (values) {
return new Promise(function (resolve, reject) {
let num = 0;
let arr = [];
for (let i = 0; i < values.length; i++) {
let current = values[i];
if (current.then && typeof current.then == "function") {
//此时是promise对象
current.then.call(current, function (val) { //此时是执行完的结果
arr[i] = val
if (++num == values.length) {
resolve(arr)
}
}, reject)
} else {
//说明是具体的值
arr[i] = current
if (++num == values.length) {
resolve(arr)
}
}
}
})
}
MyPromise.prototype.race = function (values) {
return new Promise(function (resolve, reject) {
try {
let num = 0;
let arr = [];
let current
for (let i = 0; i < values.length; i++) {
current = values[i]
if (current.then && typeof current.then == "function") {
current.then(resolve, reject)
} else {
resolve(current)
}
}
} catch (e) {
reject(e)
}
})
}
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('p1')
}, 2000)
})
promise.then(null).then(res => {
console.log(res)
})
</script>
</body>
</html>
最后分享一篇对我promise帮助很大的文章