Promise简介

Promise 是异步编程的一种解决方案: 从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果

promise有三种状态:**pending(等待态),fulfiled(成功态),rejected(失败态)** ;状态一旦改变,就不会再变。创造promise实例后,它会立即执行。

promise解决的问题:

  • 回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象
  • promise可以解决异步的问题,但不能说promise是异步的(注意promise本身是同步的

Promise的基本使用

由下面可知:thencatchfinally都是Promise的实例方法,放在Promise.prototype上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
console.log(Object.getOwnPropertyDescriptors(Promise.prototype));
// {
// constructor: {
// value: [Function: Promise],
// writable: true,
// enumerable: false,
// configurable: true
// },
// then: {
// value: [Function: then],
// writable: true,
// enumerable: false,
// configurable: true
// },
// catch: {
// value: [Function: catch],
// writable: true,
// enumerable: false,
// configurable: true
// },
// finally: {
// value: [Function: finally],
// writable: true,
// enumerable: false,
// configurable: true
// },
// [Symbol(Symbol.toStringTag)]: {
// value: 'Promise',
// writable: false,
// enumerable: false,
// configurable: true
// }
// }

创建

使用 new Promise 构造函数可以创建一个 Promise 对象,并提供一个执行器函数(executor function),该函数有两个参数,通常命名为 resolvereject

1
2
3
4
5
6
7
8
const myPromise = new Promise((resolve, reject) => {
// 异步操作
if (/* 操作成功 */) {
resolve('Promise is resolved successfully.');
} else {
reject('Promise is rejected with an error.');
}
});

使用

then() 和 catch() 方法

  • .then(onFulfilled, onRejected)当 Promise 被成功解决时,调用 onFulfilled 回调;如果被拒绝,则调用 onRejected 回调。
  • .catch(onRejected):用于指定当 Promise 被拒绝时的回调函数
1
2
3
4
5
6
7
myPromise
.then((value) => {
console.log(value); // "Promise is resolved successfully."
})
.catch((error) => {
console.error(error);
});

或者:

1
2
3
4
5
6
myPromise
.then((value) => {
console.log(value); // "Promise is resolved successfully."
}, catch((error) => {
console.error(error);
}))

finally() 方法

.finally(onFinally)无论 Promise 对象是被解决还是被拒绝,都会执行的回调函数。

1
2
3
4
myPromise
.then((value) => console.log(value))
.catch((error) => console.error(error))
.finally(() => console.log('Promise is settled.'));

链式调用

Promise then() catch() 方法返回的都是一个新的 Promise 对象,这允许进行链式调用。

1
2
3
4
5
6
7
8
9
10
11
myPromise
.then((firstResult) => {
// 处理第一个异步操作的结果
return anotherAsyncOperation();
})
.then((secondResult) => {
// 处理第二个异步操作的结果
})
.catch((error) => {
// 处理错误
});

Promise状态

三种状态

一个 Promise 对象有三种状态:

  1. Pending(进行中) :初始状态,既不是成功,也不是失败状态。
  2. Fulfilled(已成功) :操作成功完成。
  3. Rejected(已失败) :操作失败。

Promise 的状态转移是单向的,只能从 PendingFulfilledPendingRejected,不能逆向转换,也不能从成功或失败状态转回进行中状态。

resolve()的参数决定promise状态

当 Promise 的 resolve 方法被调用时,其参数决定了 Promise 的状态:

  1. 如果参数是一个普通值或普通对象(非 Promise 对象) ,则 Promise 对象变为 fulfilled(已解决)状态,并且该值成为 Promise 的结果值。
1
2
3
4
5
6
7
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success') // 传入的是一个普通值,则promise的状态会变为fulfilled
}, 1000)
})

promise.then((data) => {console.log(data);}) // success
  1. 如果参数是一个 Promise 对象,则原始 Promise 对象的状态取决于被解析的 Promise 对象的状态

    • 如果被解析的 Promise 对象是 pending 状态,则原始 Promise 对象也保持 pending 状态,直到被解析的 Promise 对象状态改变。
    • 如果被解析的 Promise 对象是 fulfilled(已解决)状态,则原始 Promise 对象也变为 fulfilled 状态,并且其值为被解析的 Promise 对象的值。
    • 如果被解析的 Promise 对象是 rejected(已拒绝)状态,则原始 Promise 对象也变为 rejected 状态,并且其原因为被解析的 Promise 对象的原因。
1
2
3
4
5
6
7
8
9
10
11
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(new Promise((resolve, reject) =>{
reject("现在状态是rejected")
// 传入的是一个promise,此时的状态就会由resolve参数promise的状态决定,也就是rejected
}))
}, 1000)
})

promise.then((data) => {console.log(data);})
.catch((error) => {console.log(error);}) // 现在状态是rejected
  1. 如果参数是一个 thenable 对象(具有 then 方法的对象) ,其行为类似于一个 Promise 对象

    • 如果 thenable 对象的 then 方法被成功调用,则原始 Promise 对象也变为 fulfilled 状态,并且其值为 thenable 对象 resolve 后的值。
    • 如果 thenable 对象的 then 方法抛出异常,则原始 Promise 对象也变为 rejected 状态,并且其原因为 thenable 对象抛出的异常。
1
2
3
4
5
6
7
8
9
10
11
12
13
const thenableObj = {
then(resolve, reject){
resolve('我是thenable对象')
}
}
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(thenableObj) // 传入的是一个thenable对象,状态就由thenable对象决定
}, 1000)
})

promise.then((data) => {console.log(data);})
.catch((error) => {console.log(error);}) // 我是thenable对象

then方法

多次调用then方法

一个promise可以多次调用then方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000)
})

// 多次调用then方法
promise.then((data) => {console.log(data);})
promise.then((data) => {console.log(data);})
promise.then((data) => {console.log(data);})
// 输出:
// success
// success
// success

then方法的返回值(链式调用)

resolve()的参数决定promise状态类似。then方法的返回值都会作为执行完then方法后新产生的promise的resolve的参数。 默认不写的话就等同于return undefined会把undefined作为resolve的参数。

  1. 返回一个普通值(数值/字符串/普通对象/undefined),那么这个返回的普通值将会作为新promiseresolve的参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000)
})

promise.then((data1) => {
console.log(data1)
return data1 // 会将data1传递给新Promise的resolve
})
.then(data2 => {console.log(data2)})
// 输出:
// success
// success
  1. 返回一个promise,则新 Promise 的状态取决于被返回的 Promise 的状态。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000)
})

promise.then((data1) => {
console.log(data1)
return new Promise((resolve,reject) => {
setTimeout(() => {
reject('failure')
}, 1000)
}) // 新Promise的状态会由这个new Promise的状态决定
})
.then(data2 => {console.log(data2)})
.catch((error) => {console.log(error)})
// 输出:
// success
// failure
  1. 返回一个 thenable 对象(具有 then 方法的对象),其行为类似于一个 Promise 对象
    1. 如果 thenable 对象的 then 方法被成功调用,则原始 Promise 对象也变为 fulfilled 状态,并且其值为 thenable 对象 resolve 后的值。
    2. 如果 thenable 对象的 then 方法抛出异常,则原始 Promise 对象也变为 rejected 状态,并且其原因为 thenable 对象抛出的异常。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const thenableObj = {
then(resolve, reject){
resolve('我是thenable对象')
}
}

const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000)
})

promise.then((data1) => {
console.log(data1)
return thenableObj // 新Promise的状态会由这个thenable对象决定
})
.then(data2 => {console.log(data2)})
.catch((error) => {console.log(error)})
// 输出:
// success
// 我是thenable对象

catch方法

catch方法不仅可以捕获reject,也可以捕获throw new Error()

1
2
3
4
5
6
7
8
9
10
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000)
})

// Promise A+的写法:
promise.then(success => console.log(success), error => console.log(error))
// ES6的写法(链式):
promise.then(success => console.log(success)).catch(error => console.log(error))
  1. 不能分开分别调用then() catch() ,要么写成Promise A+的形式,要么写成ES6的形式。但是和then一样,catch也可以进行多次调用。
  2. catch() 按照顺序的优先级来捕获rejectthrow new Error()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000)
})

promise.then(success => {
console.log(success)
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('new Promise error')
}, 1000)
})
})
.catch(error => console.log(error))

// 输出:
// success
// new Promise error

上面代码中,最开始的promiseresolve,不会捕获异常,而then返回的是一个promise,其reject,故catch会捕获到reject('new Promise error')

但下面这个例子中,最开始的promisereject,会被catch捕获到,那么后面then返回的promise,虽然是reject,但是不会被捕获到。

catch就是按照这样的顺序优先级来捕获的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
reject('failure') // 一开始就reject,则会捕获这的reject
}, 1000)
})

promise.then(success => {
console.log(success)
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('new Promise error')
}, 1000)
})
})
.catch(error => console.log(error))
// 输出:
// failure
  1. catchthen一样,也可以有返回值,而且和then一样,返回的值会被传到new Promiseresolve

finally方法

  • 不管resolve还是reject最终都会执行的。
  • 回调函数没有参数。
  • finally也可以多次调用。

Promise的类方法(静态方法)

Promise.resolve()Promise.reject()方法

用于返回成Promise。

Promise.resolve()

还是由resolve()的参数决定promise状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 传普通值(普通对象)
const promise1 = Promise.resolve({a:1, b:2})
promise1.then(data1 => console.log(data1))
// 相当于:
const promise1 = new Promise((resolve, reject) => {
resolve({a:1, b:2})
})
promise1.then(data1 => console.log(data1))



// 传一个promise
const promise2 = Promise.resolve(new Promise((resolve, reject) => resolve("hello, I'm a promise")))
promise2.then(data2 => console.log(data2))
// 相当于:
const promise2 = new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => resolve("hello, I'm a promise")))
})
promise2.then(data2 => console.log(data2))



// 传一个thenable对象
const thenableObj = {
then(resolve, reject){
resolve('我是thenable对象')
}
}
const promise3 = Promise.resolve(thenableObj)
promise3.then(data3 => console.log(data3))
// 相当于:
const promise3 = new Promise((resolve, reject) => {
resolve(thenableObj)
})
promise3.then(data3 => console.log(data3))

考考你,下面这段代码会输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Promise.resolve()
.then(() => {
console.log(0);
return Promise.resolve(4);
})
.then((res) => {
console.log(res)
})

Promise.resolve()
.then(() => {
console.log(1);
})
.then(() => {
console.log(2);
})
.then(() => {
console.log(3);
})
.then(() => {
console.log(5);
})
.then(() => {
console.log(6);
})
// 输出:0 1 2 3 4 5 6

分析:

  • 一个promiseresolve后,状态变成Fulfilled ,会把then() 里面的回调函数放到微队列里面执行;相对应的, reject后,状态变成Rejected ,会把catch() 里面的回调函数放到微队列里面执行。
  • then() 方法会返回一个promise。
  • 如果promise1resolve(普通值a) 后在then() 中return了一个新的promise(promise2),(V8源码中)那么就会把promise2.then((普通值a)=> promise1的then()返回的promise .resolve(普通值a)) 这一段代码放到微队列里面等待执行。

Promise.reject()

注意:reject可不会和resolve一样由参数来决定promise状态,不管传的参数是什么都只会执行catch

1
2
3
4
5
6
7
8
9
const thenableObj = {
then(resolve, reject){
resolve('我是thenable对象')
}
}
const promise = Promise.reject(thenableObj)
promise.then(data => console.log(data))
.catch((error) => {console.log(error)})
// 输出:{ then: [Function: then] }

Promise.all()Promise.allSettled()

Promise.all()

  • 当所有的promise都resolve后会以数组的形式返回所有resolve的结果,顺序是按照写在Promise.all() 里面的顺序,而不是按照每个promise响应的顺序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('我是promise1')
}, 1000)
})

const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('我是promise2')
}, 2000)
})

const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('我是promise3')
}, 3000)
})

Promise.all([promise3, promise2, promise1]).then(res => {
console.log(res);
})
// 输出:[ '我是promise3', '我是promise2', '我是promise1' ]
  • 只要这些promise中有一个reject了,那么就会直接catchreject的那个promise( 只会catch出最先reject的那个,一遇到reject就会立即catch)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('我是promise1')
}, 1000)
})

const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('我是promise2,reject了')
}, 2000)
})

const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('我是promise3')
}, 3000)
})

Promise.all([promise3, promise2, promise1]).then(res => {
console.log(res);
})
.catch(err => console.log(err));
// 输出:我是promise2,reject了

Promise.allSettled()

Promise.allSettled() 则会等所有promise都响应完最后直接输出一个 对象数组,里面包含每个promise的status和value/reason 顺序还是按照写在Promise.allSettled() 里面的顺序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('我是promise1')
}, 1000)
})

const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('我是promise2,reject了')
}, 2000)
})

const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('我是promise3')
}, 3000)
})

Promise.allSettled([promise3, promise2, promise1]).then(res => {
console.log(res);
})
.catch(err => console.log(err));
// 输出:
// [
// { status: 'fulfilled', value: '我是promise3' },
// { status: 'rejected', reason: '我是promise2,reject了' },
// { status: 'fulfilled', value: '我是promise1' }
// ]

Promise.race()Promise.any()

Promise.race()

会调用第一个响应完的promise的then() catch()

  • 只要有一个Promise变成fulfilled状态,那么就结束,执行相应的then()
  • 只要有一个Promise变成rejected状态,那么就结束,执行相应的catch()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('我是promise1')
}, 1000)
})

const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('我是promise2,reject了')
}, 500)
})

const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('我是promise3')
}, 3000)
})

Promise.race([promise3, promise2, promise1]).then(res => {
console.log(res);
})
.catch(err => console.log(err));
// 输出:我是promise2,reject了

Promise.any()

总是调用第一个resolve的promise的then()

  • Promise.any() 方法会等到一个fulfilled状态,才会决定新Promise的状态
  • 如果所有的Promise都是reject的,那么也会等到所有的Promise都变成rejected状态。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('我是promise1,reject了')
}, 1000)
})

const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('我是promise2,reject了')
}, 500)
})

const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('我是promise3,reject了')
}, 3000)
})

Promise.any([promise3, promise2, promise1]).then(res => {
console.log(res);
})
.catch(err => console.error(err));
// 输出:
// [AggregateError: All promises were rejected] {
// [errors]: [ '我是promise3,reject了', '我是promise2,reject了', '我是promise1,reject了' ]
// }

Promise A+ 规范与ES6的promise

  • ES6(ECMAScript 2015)中的 Promise 是语言规范的一部分,并且现代浏览器和 JavaScript 运行环境都原生支持它。
  • ES6 的 Promise 是 JavaScript 异步编程的一个基础构件,它提供了一种更合理、更强大的异步编程模型。而 Promise A+ 规范是 Promise 的行为标准,确保了不同 JavaScript 环境中 Promise 的一致性和可预测性。
  • 在实际开发中,你通常不需要自己实现 Promise,而是直接使用 ES6 提供的 Promise 对象,或者使用库和框架提供的符合 Promise A+ 规范的 Promise 实现。

ES6 Promise 的基本用法

ES6 中的 Promise是一个构造函数,是对Promise A+ 规范的实现。注意:构造函数本身不是Promise,而是其创建的对象是Promise。ES6 中的 Promise还增加了catch()finally()Promise.all()Promise.allSettled()Promise.race()Promise.any()

创建 Promise

1
2
3
4
5
6
7
8
9
const myPromise = new Promise((resolve, reject) => {
// 异步操作
const condition = true; // 假设这是异步操作的结果
if (condition) {
resolve('Promise is resolved successfully.');
} else {
reject('Promise is rejected with an error.');
}
});

使用 Promise

1
2
3
4
5
6
7
myPromise
.then((value) => {
console.log(value); // 如果 promise 被成功解决,这里会打印 value
})
.catch((error) => {
console.error(error); // 如果 promise 被拒绝,这里会打印 error
});

Promise A+ 规范

Promise A+Promise 的一个规范,早于ES6,它定义了 Promise 的行为和接口,它的出现是为了解决回调地狱的问题。ES6 中的 Promise 实现遵循了这个规范。Promise A+ 规范确保了不同 JavaScript 环境中 Promise 的一致性。

Promise A+ 规范的关键点

  1. 状态Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。
  2. thenable 对象:遵循 Promise A+ 规范的 Promise 对象被称为 thenable 对象,因为它们拥有 then 方法。
  3. 链式调用Promisethen 方法返回一个新的 Promise 对象,这允许进行链式调用。
  4. 错误处理:如果在 .then().catch() 方法中抛出错误,那么这个错误会被下一个 .catch() 方法捕获。
  5. 回调函数Promise 的构造函数接受的执行器函数(executor function)中,resolve 用于解决 Promisereject 用于拒绝 Promise
  6. 惰性执行Promise 中的异步操作是惰性执行的,即直到 Promise.then().catch() 方法被调用时才开始执行。

Promise 与 Promise A+ 的关系

  • Promise A+ 是规范:它定义了 Promise 应该如何工作,包括它的接口和行为。
  • ES6 Promise 是实现:ES6 中的 Promise 是对 Promise A+ 规范的一个具体实现。
  • 兼容性:遵循 Promise A+ 规范的任何 Promise 实现都应该与遵循相同规范的其他 Promise 实现兼容。

手写promise

手写Promise的工具函数

  • catch:
1
2
3
Promise.prototype.catch = function (onRejected) {
return this.then(null, onRejected)
}

catch 方法(Promise A+规范里面没有catch())实际上是通过调用 then 方法来实现的。具体地,它传递了 null 作为第一个参数(表示对于解决的情况不做处理),并将传入的 onRejected 回调函数作为第二个参数(用于处理拒绝的情况)。因此,当 Promise 被拒绝时,onRejected 回调函数将被调用,而对于解决的情况,则不做处理。


  • finally:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    finally(onFinally){
    return this.then(data =>{
    onFinally()
    // this的promise是成功的,那么返回的promise也是成功的
    return data
    }), err => {
    onFinally()
    // this的promise是失败的,那么返回的promise也是失败的
    throw err
    }
    }

  • resolve:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function isPromiseLike(obj){
// 满足A+规范的对象:有then方法的对象
return obj && obj.then === 'function'
}

Promise.resolve = function(value){
// 如果value是一个Promise对象,直接返回
if(value instanceof Promise) return value
// 如果value是一个thenable对象,返回一个新的Promise对象,并且将value的状态传递给新的Promise对象
if(isPromiseLike(value)){
return new Promise((resolve, reject) => {value.then(resolve, reject)})
}
// 如果value是一个普通值,返回一个新的Promise对象,状态为fulfilled
return new Promise((resolve, reject) => {resolve(value)})
}

  • reject:
    1
    2
    3
    4
    // Promise.reject(reason)返回一个状态为rejected的Promise对象
    Promise.reject = function(reason){
    return new Promise((resolve, reject) => {reject(reason)})
    }

手写Promise(完整版)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// 用常量表示状态,防止硬编码
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
// 用#表示私有属性
// 定义状态state和传的值result
#state = PENDING
#result = undefined
// 定义回调函数(then)数组
#handlers = []

// 定义改变状态的方法
#changeState(state, result){
if(this.#state !== PENDING) return // Promise状态只能改变一次
this.#state = state
this.#result = result
// 状态改变后才执行,防止异步
this.#run()
}
// 判断是否是Promise对象
#isPromiseLike(value){
// 判断是否是对象并且有then方法
return value && typeof value.then === 'function'
}
// 将函数放到微任务队列中执行
#runMicroTask(func){
// 分环境:
// node环境
if(typeof process === 'object' && typeof process.nextTick === 'function'){
process.nextTick(func)
} else if(typeof MutationObserver === 'function'){
// 浏览器环墧:通过监听文本节点变化将函数放到微任务队列中
const observer = new MutationObserver(func)
const textNode = document.createTextNode('')
observer.observe(textNode, {characterData: true})
textNode.data = 'test'
} else {
// 其他环境:通过setTimeout将函数放到微任务队列中
setTimeout(func, 0);
}
}
// 执行回调函数(then)
// 状态确定后执行callback
#runOne(callback, resolve, reject){
this.#runMicroTask(() => {
if(typeof callback !== 'function'){
// 如果callback不是函数,根据状态执行resolve或reject
const settled = this.#state === FULFILLED ? resolve : reject
settled(this.#result)
return
}
// 如果callback是函数,执行callback
// 同时也要try catch,callback执行出错时执行reject
try{
const data = callback(this.#result)
// 如果callback返回的是Promise对象,执行then方法
if(this.#isPromiseLike(data)){
data.then(resolve, reject)
} else {
resolve(data)
}
} catch (err) {
reject(err)
}
})
}
// 执行回调函数(then)数组
#run(){
if(this.#state === PENDING) return
// console.log(this.#handlers);
while(this.#handlers.length){
// 每从handlers中取出一个handler,就解构出onFulfilled, onRejected, resolve, reject
const {onFulfilled, onRejected, resolve, reject} = this.#handlers.shift()
if(this.#state === FULFILLED){
this.#runOne(onFulfilled, resolve, reject)
} else if(this.#state === REJECTED){
this.#runOne(onRejected, resolve, reject)
}
}
}
// 构造函数,传入执行器executor
constructor(executor) {
// 在构造器内部定义resolve和reject函数,防止this指向问题(绑定this)
const resolve = (data) => {
this.#changeState(FULFILLED, data)
}
const reject = (reason) => {
this.#changeState(REJECTED, reason)
}
try {
executor(resolve, reject)
// 只能捕获同步代码的错误,异步代码的错误无法捕获
}
// 如果执行器执行出错,则执行reject
catch (err) {
reject(err)
}
}
// then方法,返回一个新的Promise对象
then(onFulfilled, onRejected){
return new MyPromise((resolve, reject) => {
// 将每次调用then的onFulfilled, onRejected, resolve, reject放到handlers数组中
this.#handlers.push({
onFulfilled,
onRejected,
resolve,
reject
})
// 调用then方法时run方法
this.#run()
})
}
}

// 示例
const p = new MyPromise((resolve, reject) => {
setTimeout(()=>resolve(12), 1000);
})
p.then(result => console.log(result), err => console.log(err))
p.then(result => {
console.log(result)
return new MyPromise((resolve, reject) => {
setTimeout(()=>resolve(24), 1000);
})
}, err => console.log(err))
.then(result => console.log(result))
// 输出:(延迟1秒后)12 12 24 (两个12同时输出,24延迟1秒输出)