Promise详解

Promise详解

介绍

Promise是异步编程的一种解决方案,它提供了一种优雅和可靠的方式来处理异步操作。在创建时,Promise代表一个尚未完成但预计将来会完成的操作,通过它可以将处理程序与异步操作的最终成功值或失败原因关联起来。异步方法不会立即返回最终值,而是返回一个Promise,在将来的某个时间点提供该值。Promise的构造函数是同步执行的,而then方法是异步执行的。一旦Promise的状态改变,就不能再变。

作用

  1. 解决什么是回调地狱?
  2. 异步操作的状态管理和错误处理

状态

一个 Promise 必然处于以下三种状态之一:

  1. 待定(pending):在创建 Promise 对象时,最初处于待定状态。在 Promise 的执行器函数中调用 resolvereject 之前,都处于待定状态。一旦状态确定为 fulfilled(已兑现)或 rejected(已拒绝),则不能再次改变。

  2. 已兑现(fulfilled):一般在执行了 resolve 后,Promise 的状态会从 pending 变为 fulfilled。此时,.then() 方法中注册的成功处理函数(第一个参数函数)会被调用,并可以获取到 resolve 函数传递的值。

  3. 已拒绝(rejected):一般在执行了 reject 后,Promise 的状态会变为 rejected。此时,.then() 方法中注册的失败处理函数(第二个参数函数)会被调用,或者可以通过 .catch() 方法捕获到错误信息

创建一个Promise

你可以通过Promise构造函数创建一个新的Promise对象。构造函数接受一个执行函数,该执行函数接受两个参数:resolve和reject。这两个参数分别用于将Promise的状态变为Fulfilled或Rejected。

1
2
3
4
5
6
7
8
9
const myPromise = new Promise((resolve, reject) => {
// 异步操作
let success = true; // 模拟操作成功
if (success) {
resolve("操作成功!");
} else {
reject("操作失败!");
}
});

使用Promise

Promise对象上有两个主要的方法:thencatch,用于处理Fulfilled和Rejected状态。

  • then方法:接受两个回调函数作为参数,第一个回调函数在Promise变为Fulfilled时执行,第二个回调函数在Promise变为Rejected时执行(可选)。
1
2
3
4
5
6
7
8
myPromise.then(
(result) => {
console.log(result); // "操作成功!"
},
(error) => {
console.log(error); // "操作失败!"
}
);
  • catch方法:是then方法的语法糖,只处理Rejected状态。
1
2
3
4
5
6
7
myPromise
.then((result) => {
console.log(result); // "操作成功!"
})
.catch((error) => {
console.log(error); // "操作失败!"
});

链式调用

Promise的强大之处在于它支持链式调用,这使得我们可以顺序执行多个异步操作,而不必嵌套回调函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const fetchData = new Promise((resolve, reject) => {
setTimeout(() => resolve("数据加载完成"), 1000);
});

fetchData
.then((result) => {
console.log(result); // "数据加载完成"
return "处理数据";
})
.then((nextResult) => {
console.log(nextResult); // "处理数据"
})
.catch((error) => {
console.error(error);
});

Promise的静态方法

Promise还提供了一些静态方法,用于更方便地处理多个Promise对象。

  1. Promise.all:当所有Promise都成功时,返回一个新的Promise,其结果是所有Promise结果的数组。如果任何一个Promise被拒绝,则返回的Promise立即被拒绝。
1
2
3
4
5
6
7
8
9
10
11
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);

Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results); // [1, 2, 3]
})
.catch((error) => {
console.error(error);
});
  1. Promise.race:只要其中一个Promise成功或失败,返回的Promise就会完成,并携带该Promise的值或原因。
1
2
3
4
5
6
7
8
9
10
const promise1 = new Promise((resolve) => setTimeout(resolve, 500, 'one'));
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'two'));

Promise.race([promise1, promise2])
.then((result) => {
console.log(result); // "two"
})
.catch((error) => {
console.error(error);
});
  1. Promise.allSettled:等待所有Promise都已完成(无论成功或失败),并返回一个包含每个Promise结果的数组。
1
2
3
4
5
6
7
8
9
10
11
const promise1 = Promise.resolve(1);
const promise2 = Promise.reject('Error');
const promise3 = Promise.resolve(3);

Promise.allSettled([promise1, promise2, promise3])
.then((results) => {
results.forEach((result) => console.log(result));
// { status: 'fulfilled', value: 1 }
// { status: 'rejected', reason: 'Error' }
// { status: 'fulfilled', value: 3 }
});
  1. Promise.any:只要其中一个Promise成功,返回的Promise就会完成,并携带该Promise的值。如果所有Promise都被拒绝,则返回的Promise会被拒绝。
1
2
3
4
5
6
7
8
9
10
11
const promise1 = Promise.reject('Error1');
const promise2 = Promise.resolve('Success');
const promise3 = Promise.reject('Error2');

Promise.any([promise1, promise2, promise3])
.then((result) => {
console.log(result); // "Success"
})
.catch((error) => {
console.error(error);
});

结论

Promise通过提供一种更优雅的方式处理异步操作,解决了回调地狱的问题,使代码更加简洁、可读和可维护。通过结合使用Promise的实例方法(then和catch)以及静态方法(all、race、allSettled和any),我们可以高效地管理复杂的异步流程。在现代JavaScript开发中,Promise已经成为处理异步操作的标准方式。