前言
Promise
是 js
异步编程的核心概念之一,它为我们提供了一种更优雅的方式来处理异步操作。
本文将全面剖析 Promise
的工作原理,并逐步实现一个符合 Promise/A+
规范的 Promise 库
。
正文
一、Promise 基础概念
Promise
代表一个异步操作的最终完成(或失败)及其结果值。它有三
种状态:
- pending:
初始状态
,既不是成功,也不是失败状态 - fulfilled:意味着操作
成功
完成 - rejected:意味着操作
失败
状态一旦改变就不能再变,只能从 pending
变为 fulfilled
,或从 pending
变为 rejected
。
二、Promise 核心静态方法实现
1. Promise.resolve 实现
Promise.resolve
方法返回
一个以给定值解析后的 Promise 对象
。
1Promise.resolve = (param) => {
2 if(param instanceof Promise) return param;
3 return new Promise((resolve, reject) => {
4 if(param && param.then && typeof param.then === 'function') {
5
6 param.then(resolve, reject);
7 }else {
8 resolve(param);
9 }
10 })
11}
实现要点:
- 如果
参数
是Promise 实例
,直接返回该实例
- 如果
参数
是 thenable 对象(具有 then 方法的对象
),返回的 Promise 会跟随这个对象` 其他
情况返回一个以该值为成功状态的 Promise 对象
2. Promise.reject 实现
Promise.reject
方法返回一个带有拒绝原因
的 Promise 对象
。
1Promise.reject = function (reason) {
2 return new Promise((resolve, reject) => {
3 reject(reason);
4 });
5}
与 resolve 不同,reject 会原封不动
地将 reason 向下传递
。
三、Promise 实例方法实现
1. Promise.prototype.finally 实现
finally
方法无论 Promise 最终状态如何都会执行。
1Promise.prototype.finally = function(callback) {
2 this.then(value => {
3 return Promise.resolve(callback()).then(() => {
4 return value;
5 })
6 }, error => {
7 return Promise.resolve(callback()).then(() => {
8 throw error;
9 })
10 })
11}
实现要点:
- 无论
成功或失败
都会执行回调
- 保持原
Promise
的值
向下传
递 - 回调函数返回的
Promise
会等待执行完毕
2. Promise.prototype.then 实现
then
方法是 Promise
的核心,它返回一个新的 Promise
。
1MyPromise.prototype.then = function (onResolved, onRejected) {
2 var self = this;
3 var promise2;
4
5
6 onResolved = typeof onResolved === 'function' ? onResolved : v => v;
7 onRejected = typeof onRejected === 'function' ? onRejected : r => { throw r };
8
9 if (self.currentState === RESOLVED) {
10 return (promise2 = new MyPromise(function (resolve, reject) {
11 setTimeout(function () {
12 try {
13 var x = onResolved(self.value);
14 resolutionProcedure(promise2, x, resolve, reject);
15 } catch (reason) {
16 reject(reason);
17 }
18 });
19 }));
20 }
21
22
23}
四、Promise 高级静态方法实现
1. Promise.all 实现
Promise.all
接收一个 Promise 数组
,当所有 Promise 都成功时
返回结果数组,有一个失败则立即失败
。
1Promise.all = function(promises) {
2 return new Promise((resolve, reject) => {
3 let result = [];
4 let index = 0;
5 let len = promises.length;
6 if(len === 0) {
7 resolve(result);
8 return;
9 }
10
11 for(let i = 0; i < len; i++) {
12 Promise.resolve(promises[i]).then(data => {
13 result[i] = data;
14 index++;
15 if(index === len) resolve(result);
16 }).catch(err => {
17 reject(err);
18 })
19 }
20 })
21}
2. Promise.race 实现
Promise.race
返回第一个完成的 Promise
的结果。
1Promise.race = function(promises) {
2 return new Promise((resolve, reject) => {
3 let len = promises.length;
4 if(len === 0) return;
5 for(let i = 0; i < len; i++) {
6 Promise.resolve(promises[i]).then(data => {
7 resolve(data);
8 return;
9 }).catch(err => {
10 reject(err);
11 return;
12 })
13 }
14 })
15}
3. Promise.allSettled 实现
Promise.allSettled
等待所有 Promise 完成
,无论成功或失败
。
1function allSettled(iterable) {
2 return new Promise((resolve, reject) => {
3 function addElementToResult(i, elem) {
4 result[i] = elem;
5 elementCount++;
6 if (elementCount === result.length) {
7 resolve(result);
8 }
9 }
10
11 let index = 0;
12 for (const promise of iterable) {
13 const currentIndex = index;
14 promise.then(
15 (value) => addElementToResult(
16 currentIndex, {
17 status: 'fulfilled',
18 value
19 }),
20 (reason) => addElementToResult(
21 currentIndex, {
22 status: 'rejected',
23 reason
24 }));
25 index++;
26 }
27 if (index === 0) {
28 resolve([]);
29 return;
30 }
31 let elementCount = 0;
32 const result = new Array(index);
33 });
34}
代码:完整 Promise 实现
下面是一个符合 Promise/A+ 规范的完整实现:
1const PENDING = "pending";
2const RESOLVED = "resolved";
3const REJECTED = "rejected";
4
5function MyPromise(fn) {
6 let _this = this;
7 _this.currentState = PENDING;
8 _this.value = undefined;
9 _this.resolvedCallbacks = [];
10 _this.rejectedCallbacks = [];
11
12 _this.resolve = function (value) {
13 if (value instanceof MyPromise) {
14 return value.then(_this.resolve, _this.reject)
15 }
16 setTimeout(() => {
17 if (_this.currentState === PENDING) {
18 _this.currentState = RESOLVED;
19 _this.value = value;
20 _this.resolvedCallbacks.forEach(cb => cb());
21 }
22 })
23 };
24
25 _this.reject = function (reason) {
26 setTimeout(() => {
27 if (_this.currentState === PENDING) {
28 _this.currentState = REJECTED;
29 _this.value = reason;
30 _this.rejectedCallbacks.forEach(cb => cb());
31 }
32 })
33 }
34
35 try {
36 fn(_this.resolve, _this.reject);
37 } catch (e) {
38 _this.reject(e);
39 }
40}
41
42
43MyPromise.prototype.then = function (onResolved, onRejected) {
44 var self = this;
45 var promise2;
46
47 onResolved = typeof onResolved === 'function' ? onResolved : v => v;
48 onRejected = typeof onRejected === 'function' ? onRejected : r => { throw r };
49
50 if (self.currentState === RESOLVED) {
51 return (promise2 = new MyPromise(function (resolve, reject) {
52 setTimeout(function () {
53 try {
54 var x = onResolved(self.value);
55 resolutionProcedure(promise2, x, resolve, reject);
56 } catch (reason) {
57 reject(reason);
58 }
59 });
60 }));
61 }
62
63
64};
65
66
67function resolutionProcedure(promise2, x, resolve, reject) {
68 if (promise2 === x) {
69 return reject(new TypeError("Error"));
70 }
71
72 if (x instanceof MyPromise) {
73 if (x.currentState === PENDING) {
74 x.then(function (value) {
75 resolutionProcedure(promise2, value, resolve, reject);
76 }, reject);
77 } else {
78 x.then(resolve, reject);
79 }
80 return;
81 }
82
83 let called = false;
84 if (x !== null && (typeof x === "object" || typeof x === "function")) {
85 try {
86 let then = x.then;
87 if (typeof then === "function") {
88 then.call(
89 x,
90 y => {
91 if (called) return;
92 called = true;
93 resolutionProcedure(promise2, y, resolve, reject);
94 },
95 e => {
96 if (called) return;
97 called = true;
98 reject(e);
99 }
100 );
101 } else {
102 resolve(x);
103 }
104 } catch (e) {
105 if (called) return;
106 called = true;
107 reject(e);
108 }
109 } else {
110 resolve(x);
111 }
112}
- 状态管理:Promise 的状态一旦改变就不能再变
- 异步执行:then 方法的回调需要异步执行
- 链式调用:then 方法必须返回一个新的 Promise
- 值穿透:then 的参数如果不是函数需要忽略
- Promise 解析过程:处理 thenable 对象和循环引用
总结
Promise 的核心在于状态管理
、链式调用
和异步处理
。
个人笔记记录 2021 ~ 2025