Promise
核心逻辑promise
就是一个类,在执行这个类的时候 需要传递一个执行器(也就是里面这个回调函数,箭头函数),执行器会立即执行( 当我们new Promise
的时候 回调会立即调用)resolve
,reject
,这两个参数其实就是两个函数Promise
中有三种状态,分别为fulfilled
rejected
pending
pending
->fulfilled
pending
->rejected
resolve
->fulfilled
reject
->rejected
promise
对象以后,我们可以创建一个变量去接收promise
下面可以调用then
方法来传递两个回调函数,成功与失败,也就说当我们调用then 在这里插入代码片
方法的时候我们要去判断promise
的返回状态,如果成功则调用的第一个(成功的回调函数),失败则第二个(失败的回调函数)then
方法内部做的事情就是判断状态,如果成功则调用的第一个(成功的回调函数),失败则第二个(失败的回调函数), then
成功回调(successCallback
)有一个参数,表示成功之后返回的值value
,then
失败回调(failCallback
)后有一个返回值reason
失败原因Promise
基础代码class
关键字创建一个类 MyPromise
constructor
来接受这个构造函数,executor
代表执行器(执行器是立即执行的,执行器就代表回调函数)/*
1、通过`class`关键字创建一个类 MyPromise
2、我们需要使用构造函数constructor 来接受这个构造函数,executor代表执行器(执行器是立即执行的,执行器就代表回调函数)
*/
const PENGDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(executor) {
// 当前我们是在一个类里面,我们要通过this去访问
executor(this.resolve, this.reject)
}
/*
1、 为什么定义成箭头函数?
将来在调用resolve 和reject的时候是直接调用的,如果是普通函数,函数里面的指向-window/reject,如果是箭头函数,会改变this指向,是内部指向类的实例对象,指向promise 对象
2、 resolve 和reject 就是用来更改状态的。
3、我们要求定义状态,定义成常量,好处:复用,便于开发。
*/
// 初始状态PENGDING
status = PENGDING
/*
8、设置默认成功之后的值,失败之后的原因
*/
value = undefined
reason = undefined
/*
9、成功回调,失败回调诉默认值
*/
successCallback = undefined
failCallback = undefined
resolve = value => {
/*
4、如果状态不是等待,阻止程序向下执行,否则将状态更改为成功
*/
if (this.status !== PENGDING) return;
this.status = FULFILLED
/*
7、保存成功之后的值 ,then方法中调用失败回调(successCallback)的时候可以传递当前保存的this.value
*/
this.value = value
/*
10、判断成功回调是否存在,如果存在则调用,
*/
this.successCallback && this.successCallback(this.value)
}
reject = reason => {
/*
5、如果状态不是等待,阻止程序向下执行,否则将状态更改为失败
*/
if (this.status !== PENGDING) return;
this.status = REJECTED
/*
7、保存失败之后的原因,then方法中调用失败回调(failCallback)的时候可以传递当前保存的this.reason
*/
this.reason = reason
/*
10、判断失败回调是否存在,如果存在则调用,
*/
this.failCallback && this.failCallback(this.reason)
}
// 6、then方法 判断状态
then(successCallback, failCallback) {
if (this.status === FULFILLED) {
successCallback(this.value)
} else if (this.status === REJECTED) {
failCallback(this.reason)
} else {
// 9、这里我们处理的就是当我们处于pending 状态的时候也就是出现异步情况的时候的.首先我们把成功回调和失败回调存储起来,等异步代码执行完毕之后才执行这个成功/失败回调 -然后我们就要找成功resolve-失败reject的回调
this.successCallback = successCallback
this.failCallback = failCallback
}
}
}
//调用
let promise = new MyPromise((resolve, reject) => {
resolve('成功')
// reject('失败')
})
promise.then(value => {
console.log(value)
}, reason => {
console.log(reason)
})
let promise = new MyPromise((resolve, reject) => {
// 假设当出现异步情况
setTimeout(()=>{
resolve('成功')
},2000)
// reject('失败')
})
promise.then(value => {
console.log(value)
}, reason => {
console.log(reason)
})
1 当出现`setTimeOut` 或者其他异步的情况的时候,导致代码没有直接调用`resolve`/`reject` 函数,此时 状态是`pengding` 所以按照代码运行顺序会直接进入到`then`方法,`then`方法会先执行,但是此时因为状态一直是`pengding` 我们并不知道是调用`successCallBack` 还是failCallBack,
2 ------------所以我们先将其存储(代码注释①)起来,当异步代码执行完毕之后我们才会执行resolve
/reject
,然后去判断成功/失败回调是否存在,若存在则调用它(代码注释②)。
const PENGDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject)
}
status = PENGDING
value = undefined
reason = undefined
successCallback = undefined
failCallback = undefined
resolve = value => {
if (this.status !== PENGDING) return;
this.status = FULFILLED
this.value = value
/* 注释② */
this.successCallback && this.successCallback(this.value)
}
reject = reason => {
if (this.status !== PENGDING) return;
this.status = REJECTED
this.reason = reason
/* 注释 ② */
this.failCallback && this.failCallback(this.reason)
}
then(successCallback, failCallback) {
if (this.status === FULFILLED) {
successCallback(this.value)
} else if (this.status === REJECTED) {
failCallback(this.reason)
} else {
/* 注释①
- 这里处理的就是当处于pending ,也就是出现异步情况的时候的:
- 首先我们把成功回调和失败回调存储起来,
- 等异步代码执行完毕之后才执行这个成功/失败回调
- 然后我们就要找成功resolve-失败reject的回调
*/
this.successCallback = successCallback
this.failCallback = failCallback
}
}
}
当then
方法被多次调用的时候,每一个then
方法中传递的回调函数都是要被执行的,这个时候我们要如何处理呢?
then
方法,
let promise = new MyPromise((resolve, reject) => {
// 假设当出现异步情况
setTimeout(()=>{
resolve('成功')
},2000)
// reject('失败')
})
promise.then(value => {
console.log(value)
}, reason => {
console.log(reason)
})
promise.then(value => {
console.log(value)
}, reason => {
console.log(reason)
})
promise.then(value => {
console.log(value)
}, reason => {
console.log(reason)
})
两种情况,一种是同步的情况 ,一种是异步的情况
下面我们就详细说明:每一个then
方法的回调函数都应该存储起来,当状态变为成功或者失败的时候,在依次调用里面的回调函数 上一个实例中出现异步的情况我们每次只能存储一个回调函数,所以我们要基于上面的情况再次进行处理
undefined
改为[]空数组
,便于我们去存储多个回调函数while
) 并调用const PENGDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject)
}
status = PENGDING
value = undefined
reason = undefined
// successCallback = undefined
// failCallback = undefined
successCallback = []
failCallback = []
resolve = value => {
if (this.status !== PENGDING) return;
this.status = FULFILLED
this.value = value
// this.successCallback && this.successCallback(this.value)
// shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。
while(this.successCallback.length>0) this.successCallback.shift()(this.value)
}
reject = reason => {
if (this.status !== PENGDING) return;
this.status = REJECTED
this.reason = reason
// this.failCallback && this.failCallback(this.reason)
// shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。
while(this.failCallback.length>0) this.failCallback.shift()(this.reason)
}
then(successCallback, failCallback) {
if (this.status === FULFILLED) {
successCallback(this.value)
} else if (this.status === REJECTED) {
failCallback(this.reason)
} else {
// this.successCallback = successCallback
// this.failCallback = failCallback
this.successCallback.push(successCallback)
this.failCallback.push(failCallback)
}
}
}
打印结果
Promise
的then
方法是可以链式调用的,后面then
方法的回调函数拿到的值实质上是上一个then
方法的回调函数的返回值
下面我们来演示一下链式调用返回的普通值的时候:
let promise = new MyPromise((resolve, reject) => {
// 当出现异步情况
// setTimeout(()=>{
// resolve('成功')
// },2000)
resolve('成功')
// reject('失败')
})
promise.then(value => {
console.log(value)
return 100;
}).then(value => {
console.log(value) //100
})
下面我们通过两个步骤来实现
then
方法的链式调用then
方法是Promise
下面的,如果我们想要实现then方法下面的链式调用,那我们的每一个then
方法返回的都应该是一个Promise
对象,这样才可以链式调用then
then
方法的回调函数then
回调函数,实际上下一个then 就是我们返回这个promise2
下面的then
, 那也就是说我们调用promise
里面的resolve
方法就好了,当我们调用完resolve
之后,就实现了 const PENGDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(executor) {executor(this.resolve, this.reject)}
status = PENGDING
value = undefined
reason = undefined
successCallback = []
failCallback = []
resolve = value => {
if (this.status !== PENGDING) return;
this.status = FULFILLED
this.value = value
while(this.successCallback.length>0)
this.successCallback.shift()(this.value)
}
reject = reason => {
if (this.status !== PENGDING) return;
this.status = REJECTED
this.reason = reason
while(this.failCallback.length>0)
this.failCallback.shift()(this.reason)
}
then(successCallback, failCallback) {
/*
1. 既然我们要返回一个Promise 对象,那么我们创建一个Promise 对象,
2. 然后我们通过return 关键字 返回 promise2
3. 传递一个执行器,(立即执行)使原来的代码保持原有的功能
4. ---这样我们就实现了步骤一
*/
let promise2 = new MyPromise((resolve,reject)=>{
if (this.status === FULFILLED) {
/* 实现步骤二
①. 首先拿到函数的返回值(成功/失败)返回的promise2
②. 把返回值传递给下一个then回调函数,调用promise2里的resolve方法
*/
let x= successCallback(this.value)
resolve(x)
} else if (this.status === REJECTED) {
failCallback(this.reason)
} else {
this.successCallback.push(successCallback)
this.failCallback.push(failCallback)
}
});
return promise2
}
}
当我们以promise
对象为返回值时
let promise = new MyPromise((resolve, reject) => {
resolve('成功')
// reject('失败')
})
// 先定义一个promise 对象
function otherPromise(params) {
return new Promise((resolve,reject)=>{
resolve('other')
})
}
//
promise.then(value => {
console.log(value)
return otherPromise();
}).then(value => {
console.log(value)
})
接下来我们要去判断 x 是普通值还是promise
对象
如果是普通值,直接resolve
如果是promise
对象 查看promise
对象返回的结果
在根据promise
对象返回的结果(Promise
对象的状态),
若成功-----> 调用resolve
将成功的值传递给下一个
若失败-----> 调用reject
将失败的结果传递给下一个
const PENGDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject)
}
status = PENGDING
value = undefined
reason = undefined
successCallback = []
failCallback = []
resolve = value => {
if (this.status !== PENGDING) return;
this.status = FULFILLED
this.value = value
while (this.successCallback.length > 0)
this.successCallback.shift()(this.value)
}
reject = reason => {
if (this.status !== PENGDING) return;
this.status = REJECTED
this.reason = reason
while (this.failCallback.length > 0)
this.failCallback.shift()(this.reason)
}
then(successCallback, failCallback) {
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
let x = successCallback(this.value)
resolvePromise(x, resolve, reject)
// resolve(x)
} else if (this.status === REJECTED) {
failCallback(this.reason)
} else {
this.successCallback.push(successCallback)
this.failCallback.push(failCallback)
}
});
// 2然后我们通过return 关键字 返回promise2
return promise2
}
}
// 判断x是普通值还是Promise对象
function resolvePromise(x, resolve, reject) {
// 我们只需要判断x 是不是MyPromise 的这个实例
if (x instanceof MyPromise) {
// x.then(value => { resolve(value)}, reason => { reject(reason)})
//简化代码
x.then(resolve,reject)
} else {
resolve(x)
}
}
在then 方法中是可以返回promise
对象的,但是有一种个例情况
在then方法中 不能返回当前这个方法他所返回的这个promise 对象,
如果说你所返回的then方法返回的那个promise对象,
那这个时候就发生了promise对象的循环调用,程序是不允许的,会报错!!
我们新建一个index.html
文件,输入以下代码,
模拟演示一下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var a = new Promise(function (resolve, reject) {
resolve('100')
})
var p1 = a.then(function (value) {
console.log(value)
return p1
})
</script>
</body>
</html>
首先我们调用的时候
let promise = new MyPromise((resolve, reject) => {
resolve('成功')
// reject('失败')
})
let p1=promise.then(value => {
console.log(value)
return p1;
})
p1.then(value => {
console.log(value)
},reason=>{
console.log(reason.message)
})
1、 找到then方法
2、返回的promise对象就是promise2 ,
成功的回调返回的promise对象就是x
3、我们只需要判断promise对象和x是否相等,
如果相等则就说明是自己返回了自己,
出现问题了,我们就要执行reject,
4、在resolvePromise中处理
const PENGDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(executor) { executor(this.resolve, this.reject)}
status = PENGDING
value = undefined
reason = undefined
successCallback = []
failCallback = []
resolve = value => {
if (this.status !== PENGDING) return;
this.status = FULFILLED
this.value = value
while (this.successCallback.length > 0) this.successCallback.shift()(this.value)
}
reject = reason => {
if (this.status !== PENGDING) return;
this.status = REJECTED
this.reason = reason
while (this.failCallback.length > 0) this.failCallback.shift()(this.reason)
}
then(successCallback, failCallback) {
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
// 异步代码原因:是此过程执行完在执行词代码 是promise2 可以传值不会报错
setTimeout(()=>{
let x = successCallback(this.value)
resolvePromise(promise2,x, resolve, reject)
},0)
} else if (this.status === REJECTED) {
failCallback(this.reason)
} else {
this.successCallback.push(successCallback)
this.failCallback.push(failCallback)
}
});
return promise2
}
}
function resolvePromise(promise2,x, resolve, reject) {
// 如果相等,就说明自己反悔了自己,捕捉到了问题,提示错误
if(promise2===x){
// 使用return 是出现问题程序报错后阻止代码向下执行
return reject(new TypeError('Chaining cycle detected for promise #' ))
}
if (x instanceof MyPromise) {
x.then(resolve,reject)
} else {
resolve(x)
}
}
上述的所有我们没有对任何错误情况进行捕捉,下面我们对一些错误进行捕捉
当执行器中的代码在执行的过程当中发生错误的时候,
我们就要把执行的状态变成是失败的状态
let promise = new MyPromise((resolve, reject) => {
// 我们抛出错误演示一下
throw new Error('执行器错误')
resolve('成功')
// reject('失败')
})
promise.then(value => {
console.log(value)
},reason=>{
console.log(reason,‘=’)
})
捕捉异常处理,我们只需要在上述代码中在执行器处
通过try ,catch来捕获异常,调用reject方法打印错误
constructor(executor) {
// 执行器中捕捉错误
try{
executor(this.resolve, this.reject)
} catch (e){
// 如果捕捉到了错误 我们把错误原因e传递过去
this.reject(e)
}
// executor(this.resolve, this.reject)
}
then方法里面的回调函数,若在执行过程中报错了,
下面我们演示一下回调函数执行中异常并抛出错误。
let promise = new MyPromise((resolve, reject) => {
resolve('成功')
// reject('失败')
})
promise.then(value => {
console.log(value)
// 我们抛出错误演示一下
throw new Error('回调函数错误')
},reason=>{
console.log(reason)
}).then(value => {
console.log(value)
},reason=>{
console.log(reason.message)
})
捕捉到这个错误,并且这个错误要在下一个then方法的错误回调reject中捕捉到,并返回
then(successCallback, failCallback) {
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(()=>{
// then方法里面的回调函数中捕捉错误
try{
let x = successCallback(this.value)
resolvePromise(promise2,x, resolve, reject)
}catch(e){
reject(e)
}
},0)
} else if (this.status === REJECTED) {
failCallback(this.reason)
} else {
this.successCallback.push(successCallback)
this.failCallback.push(failCallback)
}
});
return promise2
}
我们之前处理链式调用 只处理了成功的状态 并没有处理失败的状态,
那么当失败的时候或者当代码是异步的时候都没有处理
模拟演示实现错误调用
let promise = new MyPromise((resolve, reject) => {
// resolve('成功')
reject('失败')
})
promise.then(value => {
// console.log(value)
},reason=>{
console.log(reason)
return "失败"
}).then(value => {
console.log(value,'捕捉错误回调')
})
捕捉代码处理,在then方法中
then(successCallback, failCallback) {
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(()=>{
// then方法里面的回调函数中捕捉错误
try{
let x = successCallback(this.value)
resolvePromise(promise2,x, resolve, reject)
}catch(e){
reject(e)
}
},0)
} else if (this.status === REJECTED) {
// then方法里面的失败函数中捕捉错误
setTimeout(()=>{
try{
let x = failCallback(this.reason)
resolvePromise(promise2,x, resolve, reject)
}catch(e){
reject(e)
}
},0)
} else {
this.successCallback.push(successCallback)
this.failCallback.push(failCallback)
}
});
return promise2
}
let promise = new MyPromise((resolve, reject) => {
setTimeout(()=>{
resolve('成功....')
},2000)
// resolve('成功')
// reject('失败')
})
promise.then(value => {
console.log(value)
return 'aaaa'
},reason=>{
console.log(reason)
}).then(value => {
console.log(value,'捕捉错误回调')
})
捕捉处理
之前我们链式调用的时候是push到一个数组里,
那这里呢我们需要push一个函数进去,
在这个函数里面进行函数回调 成功/失败
const PENGDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(executor) {
try{
executor(this.resolve, this.reject)
} catch (e){
this.reject(e)
}
}
status = PENGDING
value = undefined
reason = undefined
successCallback = []
failCallback = []
resolve = value => {
if (this.status !== PENGDING) return;
this.status = FULFILLED
this.value = value
// 当处理异步 捕捉错误的时候这个手已经不需要传值了,
while (this.successCallback.length > 0) this.successCallback.shift()()
}
reject = reason => {
if (this.status !== PENGDING) return;
this.status = REJECTED
this.reason = reason
// 当处理异步 捕捉错误的时候这个手已经不需要传值了,
while (this.failCallback.length > 0) this.failCallback.shift()()
}
then(successCallback, failCallback) {
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(()=>{
// then方法里面的回调函数中捕捉错误
try{
let x = successCallback(this.value)
resolvePromise(promise2,x, resolve, reject)
}catch(e){
reject(e)
}
},0)
} else if (this.status === REJECTED) {
// failCallback(this.reason)
setTimeout(()=>{
// then方法里面的回调函数中捕捉错误
try{
let x = failCallback(this.reason)
resolvePromise(promise2,x, resolve, reject)
}catch(e){
reject(e)
}
},0)
} else {
this.successCallback.push(()=>{
setTimeout(()=>{
// then方法里面的回调函数中捕捉错误
try{
let x = successCallback(this.value)
resolvePromise(promise2,x, resolve, reject)
}catch(e){
reject(e)
}
},0)
})
this.failCallback.push(()=>{
setTimeout(()=>{
// then方法里面的回调函数中捕捉错误
try{
let x = failCallback(this.reason)
resolvePromise(promise2,x, resolve, reject)
}catch(e){
reject(e)
}
},0)
})
}
});
return promise2
}
}
处理方法
// 在then 方法中添加
successCallback = successCallback ? successCallback : value => value;
failCallback = failCallback ? failCallback : reason => { throw reason }
//成功调用
let promise = new MyPromise((resolve, reject) => {
resolve('成功....')
})
promise.then().then().then(value=>console.log(value))
// 失败调用
let promise = new MyPromise((resolve, reject) => {
reject('失败')
})
promise.then().then().then(value=>console.log(value),reason=>{console.log(reason)})
function p1(){
return new MyPromise(function(resolve,reject){
setTimeout(function(){
resolve('p1')
},2000)
})
}
function p2(){
return new MyPromise(function(resolve,reject){
resolve('p2')
})
}
上述代码中如果我们先调用p1(),后调用p2(),按照正常代码执行顺序我们肯定先得到的是p2()后得到的是p1()(p1中有延时定时器),
如果我们放置于Promise.all 中
Promise.all(['a','b',p1(),p2(),'c']).then(function(result){
// return ->['a','b','p1','p2','c']
})
我们就会是先得到 p1() 然后是p2()
那么下面我们依然按照之前的Promise基础上继续去开发all方法
1、参数是一个数组 arr
2、我们就要去循环这个数组进行循环处理,在循环的过程中,我们要判断是普通值还是promise对象
3、如果是普通值,直接放到结果数组中,
如果是promise 对象,就先去执行这个promise对象,再把promsie的结果放到结果数组中
如果状态是成功的那么再把promsie的结果放到结果数组中
如果状态都是成功的all方法最后的结果就是成功的;
如果有一个是失败的那么最后的结果就是失败的的;
4、那么就需要我们先声明一个结果数组result
5、然后我们定义一个变量index 初始为0
去判断当前参数中异步的代码是否都执行完毕,
我们在每次把参数执行结果放入结果数组中时 index++,
当index === 参数数组长度 的时候 就代表 所有参数都执行完毕,
这个之后我们执行resolve(),
static all(arr){
let result=[]
let index=0
return new Promise((resolve,reject)=>{
function addData(key,value) {
result[key]=value
index++
if(index===arr.length){
resolve(result)
}
}
for(let i=0;i<arr.length;i++){
let current=arr[i];
if(current instanceof MyPromise){
current.then(value=>addData(i,value),reason=>reject(reason))
}else{
addData(i,arr[i])
}
}
})
}
使用Promise.all() 执行
MyPromise.all(['a','b',p1(),p2(),'c']).then(result=>console.log(result))
//[ 'a', 'b', 'p1', 'p2', 'c' ]
static resolve(value){
if(value instanceof MyPromise){
return value
}else{
return new Promise(resolve=>resolve(value))
}
}
然后我们来验证一下
function p1(){
return new MyPromise(function(resolve,reject){
setTimeout(function(){
resolve('p1')
},2000)
})
}
MyPromise.resolve(100).then(value=>console.log(value))
//100
MyPromise.resolve(p1()).then(value=>console.log(value))
//p1 2s后打印
finally 方法不是一个静态方法,要定义在类的原型对象上
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function p1() {
return new Promise(function (resolve, reject) {
resolve('finally')
})
}
p1().finally(() => {
console.log('finally')
}).then(value => console.log(value))
</script>
</body>
</html>
finally(callback){
return this.then(value=>{
callback()
// 若成功则传递给下一个then返回值value
return value
},reason=>{
callback()
// 若失败则通过throw传递给下一个then 失败理由 reason
throw reason
})
}
调用案例
function p2(){
return new MyPromise(function(resolve,reject){
reject('p2 reject')
})
}
p2().finally(() => {
console.log('finally')
}).then(value => console.log(value),reason=>console.log(reason))
// finally
//p2 reject
如果我们在调用的时候return的 是一个异步执行的promise对象,那我们调用时。如下代码调用,
function p1(){
return new MyPromise(function(resolve,reject){
setTimeout(function(){
resolve('p1')
},2000)
})
}
function p2(){
return new MyPromise(function(resolve,reject){
resolve('p2 resolve')
})
}
p2().finally(() => {
console.log('finally')
//异步
return p1()
}).then(
value => console.log(value),
reason=>console.log(reason)
)
//这个时候控制台输出为 立即 finally p2 resolve, 并没有两秒的延迟,
上述调用中我们想要实现的是延迟两秒输出,但是因为本身自带的功能导致没有延迟,失去我们想要的效果,所以我们在promise
代码中借助resolve
方法,
callback
方法的返回值promise
对象,然后等待等待primise
对象的执行完成,然后返回结果promise
对象我们就等你执行完成,然后再返回value
finally(callback){
return this.then(value=>{
// callback()
return MyPromise.resolve(callback()).then(()=>value)
// 若成功则传递给下一个then返回值value
// return value
},reason=>{
return MyPromise.resolve(callback()).then(()=>{throw reason})
callback()
// 若失败则通过throw传递给下一个then 失败理由 reason
throw reason
})
}
//finally 两秒后 p2 resolve
catch 方法的作用是用来处理当前这个promise对象最终的状态为失败的情况的,也就是说我们是可以不传递失败回调的,这时候这个失败回调就会被catch方法所捕获,从而就会传入到catch方法中的回调函数,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function p1() {
return new Promise(function (resolve, reject) {
resolve('catch')
})
}
p1()
.then(value=>console.log(value))
.catch(reason=>console.log(reason))
</script>
</body>
</html>
下面我们在promise 源码上加上这个方法,来捕获失败回调函数
catch(failCallback){
return this.then(undefined,failCallback)
}
我们来调用一下
function p2(){
return new MyPromise(function(resolve,reject){
reject('p2 reject')
// resolve('p2 resolve')
})
}
p2().then().catch(reason=>console.log(reason))
// p2 reject
const PENGDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(executor) {
try {
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}
status = PENGDING
value = undefined
reason = undefined
successCallback = []
failCallback = []
resolve = value => {
if (this.status !== PENGDING) return;
this.status = FULFILLED
this.value = value
while (this.successCallback.length > 0) this.successCallback.shift()()
}
reject = reason => {
if (this.status !== PENGDING) return;
this.status = REJECTED
this.reason = reason
while (this.failCallback.length > 0) this.failCallback.shift()()
}
then(successCallback, failCallback) {
successCallback = successCallback ? successCallback : value => value;
failCallback = failCallback ? failCallback : reason => { throw reason }
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
} else if (this.status === REJECTED) {
// failCallback(this.reason)
setTimeout(() => {
try {
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
} else {
this.successCallback.push(() => {
setTimeout(() => {
try {
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
this.failCallback.push(() => {
setTimeout(() => {
try {
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
}
});
return promise2
}
finally(callback){
return this.then(value=>{
// callback()
return MyPromise.resolve(callback()).then(()=>value)
// return value
},reason=>{
return MyPromise.resolve(callback()).then(()=>{throw reason})
callback()
throw reason
})
}
catch(failCallback){
return this.then(undefined,failCallback)
}
static all(arr){
let result=[]
let index=0
return new Promise((resolve,reject)=>{
function addData(key,value) {
result[key]=value
index++
if(index===arr.length){
resolve(result)
}
}
for(let i=0;i<arr.length;i++){
let current=arr[i];
if(current instanceof MyPromise){
current.then(value=>addData(i,value),reason=>reject(reason))
}else{
addData(i,arr[i])
}
}
})
}
static resolve(value){
if(value instanceof MyPromise){
return value
}else{
return new Promise(resolve=>resolve(value))
}
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #' ))
}
if (x instanceof MyPromise) {
x.then(resolve, reject)
} else {
resolve(x)
}
}
以上内容均为个人学习笔记,不存在任何其他或者商业行为 ,如有侵权或者其他,必删除。请私聊或者评论告知。