【javaScript】实现简易版promise

实现简易版promise

相关文章

实现简易版promise


一、基本功能

异步操作的管理

Promise 提供了一种标准化的方式来管理异步操作,使得代码更加清晰易读。通过 Promise,可以更容易地组织和控制异步操作的执行顺序,避免了回调地狱(Callback Hell)的问题。

状态管理

Promise 具有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。异步操作初始状态为 pending,当操作成功完成时变为 fulfilled,当操作发生错误时变为 rejected。Promise 可以根据状态的变化来执行相应的回调函数,从而实现对异步操作状态的管理。

链式调用

Promise 的 then 方法返回一个新的 Promise 对象,使得可以进行链式调用。这种链式调用的方式使得可以按照顺序处理异步操作的结果,而不需要嵌套多层回调函数,提高了代码的可读性和可维护性。

错误处理

Promise 提供了 catch 方法用于捕获异步操作中的错误。在链式调用中,可以通过 catch 方法统一处理所有链条中的错误,避免了错误沿着链条传播而导致程序崩溃。

二、实现步骤

创建 Promise 类和构造函数

首先,我们创建一个名为 MyPromise 的类,这个类将表示我们手写的 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
constructor(executor) {
// 初始化 Promise 的状态和值
this.state = "pending";
this.value = undefined;
this.error = undefined;
this.onResolveCallbacks = [];
this.onRejectCallbacks = [];

// 定义 resolve 函数,用于完成 Promise
const resolve = (value) => {
if (this.state === "pending") {
this.state = "fulfilled";
this.value = value;
// 执行所有注册的 onFulfilled 回调函数
this.onResolveCallbacks.forEach((callback) => callback());
}
};

// 定义 reject 函数,用于拒绝 Promise
const reject = (error) => {
if (this.state === "pending") {
this.state = "rejected";
this.error = error;
// 执行所有注册的 onRejected 回调函数
this.onRejectCallbacks.forEach((callback) => callback());
}
};

try {
// 执行 executor 函数,将 resolve 和 reject 函数作为参数传递给 executor
executor(resolve, reject);
} catch (error) {
// 如果在执行 executor 函数的过程中出现异常,则直接拒绝 Promise
reject(error);
}
}
  • 状态管理: 初始化了 Promise 的状态为 ‘pending’,并提供了 resolve 和 reject 函数用于改变 Promise 的状态为 ‘fulfilled’ 或 ‘rejected’。这样可以在异步操作执行完成后改变 Promise 的状态。

  • 执行器函数执行: 在构造函数中执行了传入的执行器函数 executor,并将 resolve 和 reject 函数作为参数传入执行器函数中。这样可以让执行器函数决定何时调用 resolve 或 reject 函数,从而改变 Promise 的状态。

  • 回调函数注册和执行: 提供了 onResolveCallbacks 和 onRejectCallbacks 数组,用于存储成功和失败时的回调函数。当调用 resolve 或 reject 函数时,会遍历相应的回调函数数组,并执行其中的回调函数。这样可以在 Promise 状态改变时执行注册的回调函数。

  • 异常处理: 使用 try…catch 语句捕获执行器函数中可能抛出的异常,如果有异常则将 Promise 的状态改为 ‘rejected’,并传入异常信息。这样可以确保 Promise 在执行过程中出现异常时能够正确处理异常情况。

实现 then 方法

接下来,我们实现 then 方法,用于注册成功和失败的回调函数。在 then 方法中,我们需要判断当前 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
then(onResolve, onReject) {
// 将 onResolve 和 onReject 转换为函数,以支持链式调用
onResolve = typeof onResolve === "function" ? onResolve : (v) => v;
onReject =
typeof onReject === "function"
? onReject
: (err) => {
throw err;
};

// 创建一个新的 Promise 对象
let promise = new MyPromise((resolve, reject) => {
// 如果当前 Promise 已经完成,则直接处理当前状态的值
if (this.state === "fulfilled") {
try {
let x = onResolve(this.value);
// 处理 then 方法返回的值
resolvePromise(promise, x, resolve, reject);
} catch (e) {
// 如果执行 onResolve 函数过程中出现异常,则直接拒绝 Promise
reject(e);
}
}

// 如果当前 Promise 已经被拒绝,则直接处理当前状态的错误
if (this.state === "rejected") {
try {
let x = onReject(this.error);
// 处理 then 方法返回的值
resolvePromise(promise, x, resolve, reject);
} catch (e) {
// 如果执行 onReject 函数过程中出现异常,则直接拒绝 Promise
reject(e);
}
}

// 如果当前 Promise 还处于 pending 状态,则将 onResolve 和 onReject 回调函数添加到对应的数组中
if (this.state === "pending") {
this.onResolveCallbacks.push(() => {
try {
let x = onResolve(this.value);
// 处理 then 方法返回的值
resolvePromise(promise, x, resolve, reject);
} catch (e) {
// 如果执行 onResolve 函数过程中出现异常,则直接拒绝 Promise
reject(e);
}
});
this.onRejectCallbacks.push(() => {
try {
let x = onReject(this.error);
// 处理 then 方法返回的值
resolvePromise(promise, x, resolve, reject);
} catch (e) {
// 如果执行 onReject 函数过程中出现异常,则直接拒绝 Promise
reject(e);
}
});
}
});

// 返回新的 Promise 对象
return promise;
}
  • 注册成功和失败回调函数: then 方法允许用户注册成功和失败时的回调函数,分别为 onResolve 和 onReject。

  • 根据 Promise 状态执行回调函数: 当 Promise 的状态为 fulfilled(成功)时,会执行注册的成功回调函数 onResolve;当 Promise 的状态为 rejected(失败)时,会执行注册的失败回调函数 onReject。

  • 处理成功回调函数返回的结果: 如果成功回调函数返回一个 Promise 对象 result,则会继续链式调用,将新的 Promise 的 resolve 和 reject 函数传入 result 的 then 方法中。

  • 处理失败回调函数返回的结果: 如果失败回调函数返回一个 Promise 对象 result,则会继续链式调用,将新的 Promise 的 resolve 和 reject 函数传入 result 的 then 方法中。

  • 支持链式调用: then 方法返回一个新的 Promise 对象,使得可以链式调用多个 then 方法。

  • 处理异步操作: then 方法中通过判断当前 Promise 的状态来决定执行成功或失败回调函数,并支持异步操作。当 Promise 的状态为 pending 时,将回调函数保存在对应的数组中,等待 Promise 状态改变后再执行。

  • 异常处理: 通过 try…catch 语句捕获回调函数执行过程中可能抛出的异常,如果有异常则将新的 Promise 的状态改为 rejected,并传入异常信息。

实现 catch 方法

接下来,我们实现 catch 方法,用于捕获 Promise 的异常。catch 方法实际上就是 then 方法的一个特殊版本,只处理失败的情况。

1
2
3
4
catch(onReject) {
// 对 catch 方法的实现,等价于调用 then 方法并传递 null 作为 onResolve 参数
return this.then(null, onReject);
}
  • 捕获异常: catch 方法用于捕获 Promise 的异常,当 Promise 进入 rejected 状态时,即表示出现了异常或错误,catch 方法会执行传入的 onReject 回调函数来处理这个异常。

  • 保持链式调用: catch 方法内部仍然是通过调用 then 方法来实现的,因此保持了链式调用的特性,可以在 catch 方法后继续调用 then 方法或其他 Promise 方法,保持了代码的清晰和流畅。

实现链式调用

resolvePromise 函数的主要功能是处理 Promise 链中 then 方法返回的值,以确保 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
const resolvePromise = (promise2, x, resolve, reject) => {
// 如果 x 是一个 Promise 对象,则等待它的状态确定
if (x instanceof MyPromise) {
x.then(resolve, reject);
} else if (x !== null && (typeof x === "object" || typeof x === "function")) {
// 如果 x 是一个对象或者函数
let thenCalled = false;
try {
const then = x.then;
if (typeof then === "function") {
// 如果 x 有 then 方法,调用 then 方法,注意这里使用了 call,确保 this 指向 x
then.call(
x,
// 这是 then 方法的 onFulfilled 回调
(y) => {
// 如果 then 方法已经被调用过,则直接返回,保证 onFulfilled 和 onRejected 只会被调用一次
if (!thenCalled) {
thenCalled = true;
// 递归调用 resolvePromise,处理 then 方法返回的值
resolvePromise(promise2, y, resolve, reject);
}
},
// 这是 then 方法的 onRejected 回调
(r) => {
// 如果 then 方法已经被调用过,则直接返回
if (!thenCalled) {
thenCalled = true;
// 如果 then 方法的 onRejected 被调用,则直接将错误传递给下一个 Promise
reject(r);
}
}
);
} else {
// 如果 then 不是一个函数,则直接完成 promise
resolve(x);
}
} catch (error) {
// 如果在调用 then 方法的过程中出现异常,则直接将异常传递给下一个 Promise
if (!thenCalled) {
thenCalled = true;
reject(error);
}
}
} else {
// 如果 x 不是一个对象或者函数,则直接完成 promise
resolve(x);
}
};
  • 处理 Promise 对象:如果当前 then 方法返回的值是一个 Promise 对象,则等待其状态确定,并根据其状态来决定当前 Promise 的状态。

  • 处理 then 方法返回值:如果当前 then 方法返回的值是一个对象或者函数,并且具有 then 方法,则调用其 then 方法,并根据其返回值来决定当前 Promise 的状态。

  • 处理非 Promise 对象:如果当前 then 方法返回的值不是一个对象或者函数,则直接使用该值来完成当前 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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
const resolvePromise = (promise2, x, resolve, reject) => {
// 如果 x 是一个 Promise 对象,则等待它的状态确定
if (x instanceof MyPromise) {
x.then(resolve, reject);
} else if (x !== null && (typeof x === "object" || typeof x === "function")) {
// 如果 x 是一个对象或者函数
let thenCalled = false;
try {
const then = x.then;
if (typeof then === "function") {
// 如果 x 有 then 方法,调用 then 方法,注意这里使用了 call,确保 this 指向 x
then.call(
x,
// 这是 then 方法的 onFulfilled 回调
(y) => {
// 如果 then 方法已经被调用过,则直接返回,保证 onFulfilled 和 onRejected 只会被调用一次
if (!thenCalled) {
thenCalled = true;
// 递归调用 resolvePromise,处理 then 方法返回的值
resolvePromise(promise2, y, resolve, reject);
}
},
// 这是 then 方法的 onRejected 回调
(r) => {
// 如果 then 方法已经被调用过,则直接返回
if (!thenCalled) {
thenCalled = true;
// 如果 then 方法的 onRejected 被调用,则直接将错误传递给下一个 Promise
reject(r);
}
}
);
} else {
// 如果 then 不是一个函数,则直接完成 promise
resolve(x);
}
} catch (error) {
// 如果在调用 then 方法的过程中出现异常,则直接将异常传递给下一个 Promise
if (!thenCalled) {
thenCalled = true;
reject(error);
}
}
} else {
// 如果 x 不是一个对象或者函数,则直接完成 promise
resolve(x);
}
};

class MyPromise {
constructor(executor) {
// 初始化 Promise 的状态和值
this.state = "pending";
this.value = undefined;
this.error = undefined;
this.onResolveCallbacks = [];
this.onRejectCallbacks = [];

// 定义 resolve 函数,用于完成 Promise
const resolve = (value) => {
if (this.state === "pending") {
this.state = "fulfilled";
this.value = value;
// 执行所有注册的 onFulfilled 回调函数
this.onResolveCallbacks.forEach((callback) => callback());
}
};

// 定义 reject 函数,用于拒绝 Promise
const reject = (error) => {
if (this.state === "pending") {
this.state = "rejected";
this.error = error;
// 执行所有注册的 onRejected 回调函数
this.onRejectCallbacks.forEach((callback) => callback());
}
};

try {
// 执行 executor 函数,将 resolve 和 reject 函数作为参数传递给 executor
executor(resolve, reject);
} catch (error) {
// 如果在执行 executor 函数的过程中出现异常,则直接拒绝 Promise
reject(error);
}
}

then(onResolve, onReject) {
// 将 onResolve 和 onReject 转换为函数,以支持链式调用
onResolve = typeof onResolve === "function" ? onResolve : (v) => v;
onReject =
typeof onReject === "function"
? onReject
: (err) => {
throw err;
};

// 创建一个新的 Promise 对象
let promise = new MyPromise((resolve, reject) => {
// 如果当前 Promise 已经完成,则直接处理当前状态的值
if (this.state === "fulfilled") {
try {
let x = onResolve(this.value);
// 处理 then 方法返回的值
resolvePromise(promise, x, resolve, reject);
} catch (e) {
// 如果执行 onResolve 函数过程中出现异常,则直接拒绝 Promise
reject(e);
}
}

// 如果当前 Promise 已经被拒绝,则直接处理当前状态的错误
if (this.state === "rejected") {
try {
let x = onReject(this.error);
// 处理 then 方法返回的值
resolvePromise(promise, x, resolve, reject);
} catch (e) {
// 如果执行 onReject 函数过程中出现异常,则直接拒绝 Promise
reject(e);
}
}

// 如果当前 Promise 还处于 pending 状态,则将 onResolve 和 onReject 回调函数添加到对应的数组中
if (this.state === "pending") {
this.onResolveCallbacks.push(() => {
try {
let x = onResolve(this.value);
// 处理 then 方法返回的值
resolvePromise(promise, x, resolve, reject);
} catch (e) {
// 如果执行 onResolve 函数过程中出现异常,则直接拒绝 Promise
reject(e);
}
});
this.onRejectCallbacks.push(() => {
try {
let x = onReject(this.error);
// 处理 then 方法返回的值
resolvePromise(promise, x, resolve, reject);
} catch (e) {
// 如果执行 onReject 函数过程中出现异常,则直接拒绝 Promise
reject(e);
}
});
}
});

// 返回新的 Promise 对象
return promise;
}

catch(onReject) {
// 对 catch 方法的实现,等价于调用 then 方法并传递 null 作为 onResolve 参数
return this.then(null, onReject);
}
}

// 示例用法
new MyPromise((resolve, reject) => {
setTimeout(() => {
reject("111");
}, 1000);
}).then((e) => {
console.log("成功:" + e);
})
.catch((e) => {
console.log("失败:" + e);
});


喜欢这篇文章?打赏一下支持一下作者吧!
【javaScript】实现简易版promise
https://www.cccccl.com/20231101/javascript/实现简易版promise/
作者
Jeffrey
发布于
2023年11月1日
许可协议