Promise 实现 JS 异步编程

三葉Leaves Author

Promise 内部

promise 用于处理异步函数,有几个关键点:

  1. 创建对象实例的时候,promise 里的代码会立刻执行

所以事实上,一般往 promise 里放 setTimeout 这种异步代码。

  1. promise 内部一般会使用两个方法:
  • resolve()
    成功时候使用,对应 已兑现(fulfilled) 状态

  • reject()
    失败时候使用,对应 已拒绝(rejected) 状态

在这两个方法使用之前,promise 会处在 待定(pending) 状态

下面的一段伪代码,模拟 promise 内部进行一个异步网络请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
function fetchData(success = true) {
return new Promise((resolve, reject) => {
console.log("开始请求数据...");

setTimeout(() => {
if (success) {
resolve({ code: 200, data: "这里是返回的数据" });
} else {
reject(new Error("请求失败:网络错误"));
}
}, 1000);
});
}

.then 和 .catch

  1. 成功或失败以后做什么?

刚刚说到,创建对象实例的时候,promise 里的代码会立刻执行。之后在成功或者失败后,我们会在 resolve() 或者 reject() 里放数据。那这个数据有什么用呢?

创建的实例会有 .then().catch() 两个方法,用于定义上文 promise 内部的函数执行成功或者失败之后,程序需要执行的后续操作。

  • .then() 方法里可以定义一个形参,这个形参等于上文中 resolve() 括号里的东西。resolve() 括号里一般会塞关键的结果数据。
  • .catch() 里的形参等于上文中 reject() 括号里的东西,这里面什么都能塞,如果塞的是字符串,那后面 .catch(e) 里的形参 e 也会是一个字符串。但是尽管如此,通常塞一个 Error 对象更合适。

在成功或者失败后,.then() 或者 .catch() 里的代码就会触发执行。
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
function fetchData(success = true) {
return new Promise((resolve, reject) => {
console.log("开始请求数据...");

setTimeout(() => {
if (success) {
resolve({ code: 200, data: "这里是返回的数据" });
} else {
reject(new Error("请求失败:网络错误"));
}
}, 1000);
});
}

fetchData(true)
.then(result => {

// 请求成功: { code: 200, data: '这里是返回的数据' }

console.log("请求成功:", result);

// 继续处理下一个操作
return "处理完毕";
})
.then(nextStep => {

// 下一步操作: 处理完毕

console.log("下一步操作:", nextStep);

})

.catch(err => {

// 请求出错: 请求失败:网络错误

console.error("请求出错:", err.message);
})
.finally(() => {
console.log("请求结束,不管成功或失败都会执行这里");
});

链式调用

从上面的示例代码中可以看到有这样的部分:

1
2
3
4
5
.then(result => {
console.log("请求成功:", result);
// 继续处理下一个操作
return "处理完毕";
})

值得注意的是,这里 return 的信息在下面第二个 then 里面,居然被作为了形参的值继续使用,这其实就是链式调用的特性。

每一个 then 默认都会 return 一个新的 promise 对象,如果函数代码中 return 了一个非 Promise 的值(比如一个数字或字符串),这个值会被自动包装在一个 resolved 的 Promise 中。上面的代码其实等价于:

1
return Promise.resolve("处理完毕");

如此一来,即便有很多个异步函数嵌套异步函数,用这种方法也能轻松化解成一长串线性的 .then() 了,从而解决回调函数地狱或者噩梦金字塔的问题。

  • 标题: Promise 实现 JS 异步编程
  • 作者: 三葉Leaves
  • 创建于 : 2025-06-17 00:00:00
  • 更新于 : 2025-07-10 13:40:50
  • 链接: https://blog.oksanye.com/9c7fd22a9f27/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
Promise 实现 JS 异步编程