likes
comments
collection
share

复习一下Promise方法

作者站长头像
站长
· 阅读数 44

Promise是一种解决JavaScript异步编程的方法,现在已经广泛应用于现代Web开发中。Promise提供了一种可以将异步操作作为一个对象来处理和操作的方法,使得异步代码更加易于理解和维护。

promise实例有哪些状态,怎么改变状态

Promise的实例有三个状态:

  • Pending(进行中)
  • Resolved(已完成)
  • Rejected(已拒绝)

当把一件事情交给promise时,它的状态就是Pending,任务完成了状态就变成了Resolved、没有完成失败了就变成了Rejected。

如何改变 promise 的状态

  • resolve(value): 如果当前是 pending 就会变为 resolved
  • reject(error): 如果当前是 pending 就会变为 rejected
  • 抛出异常: 如果当前是 pending 就会变为 rejected

注意:一旦从进行状态变成为其他状态就永远不能更改状态了。

Promise的主要方法包括以下几个:

1. Promise.resolve(value)

Promise.resolve方法返回一个已 fulfilled/resolved 的Promise对象。

应用场景:在实现异步调用时,Promise.resolve() 可以省略不必要的异步步骤,直接返回一个已成功解决的Promise对象,方便后续处理。

Promise.resolve('foo')
  .then(value => console.log(value));
// expected output: "foo"

2. Promise.reject(reason)

Promise.reject方法返回一个已 rejected 的Promise对象。

应用场景:在实现异步调用时,可以使用Promise.reject() 来直接返回失败的 Promise对象,方便后续处理。

Promise.reject(new Error('fail'))
  .catch(error => console.log(error));
// expected output: Error: fail

3. then(onFulfilled, onRejected)

then方法接收两个参数 onFulfilled 和 onRejected,分别是Promise对象 fulfilled/resolved 和 rejected 的处理函数。

应用场景:用来处理异步操作的结果。当 Promise对象状态从 pending 变为 fulfilled/resolved 时,会自动调用 onFulfilled 函数;当从 pending 变为 rejected时,会自动调用 onRejected 函数。

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

promise.then((value) => {
  console.log(value);
}).catch((error) => {
  console.log(error);
});

4. Promise.all

Promise.all方法接收一个可迭代对象(例如数组)作为参数,返回一个Promise对象。该Promise对象会在所有可迭代对象中的Promise对象都 fulfilled/resolved 之后才resolved并返回结果,如果其中有一个Promise rejected 则会中断。

应用场景:多个异步操作需要同时完成或并发请求一组数据时使用此方法。

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(values => {
  console.log(values);
});

5. Promise.race

Promise.race 是一个在 ES2015 中引入的方法,接受一个 Promise 实例数组,返回一个新的 Promise 实例,该实例在输入数组中的任何一个 Promise 实例状态发生变化时,立即采用该 Promise 实例的状态。

以下是一个使用 Promise.race 的示例,假设我们有三个 Promise 实例:

const p1 = new Promise((resolve) => setTimeout(resolve, 1000, 'Promise 1'));
const p2 = new Promise((resolve) => setTimeout(resolve, 500, 'Promise 2'));
const p3 = new Promise((resolve, reject) => setTimeout(reject, 1500, 'rejected promise'));

Promise.race([p1, p2, p3])
  .then((result) => console.log(result))
  .catch((error) => console.error(error));

在上面的示例中,Promise.race 接收到包含三个 Promise 实例的数组,分别在 1 秒、500 毫秒和 1.5 秒后进入不同的状态。因为 p2 是最快完成的 Promise 实例,所以 Promise.race 立即采用 p2 的状态,并将它的结果 'Promise 2' 作为输出结果。如果 p2 的延迟时间增加到 1500 毫秒,那么 Promise.race 将采用 p3 的状态,因为它是最先改变状态的 Promise 实例,其结果为一个被拒绝的 Promise 实例,并输出拒绝原因。

需要注意的是,Promise.race 方法可能返回一个解析的 Promise 或拒绝的 Promise,具体取决于数组中的哪个 Promise 状态改变。因此,为了减少竞争条件,通常需要确保在数组中的每个 Promise 实例都至少在某个条件下完成。另外,需要注意 Promise.race 的状态仅取决于数组中的第一个 Promise 实例状态发生变化的 Promise,因此其他 Promise 实例的状态可能会被忽略。

如果你需要等待数组中的所有 Promise 实例都完成,可以使用 Promise.all 方法来处理。

6.Promise.any

Promise.any 是一个在 ES2021 中引入的全局方法,用于处理一个有多个 Promise 实例的并发场景。它接受一个 Promise 实例数组,并返回一个新的 Promise 实例,该实例在输入数组中的任何一个 Promise 实例成功解析时解析,若输入数组中的所有 Promise 实例都被拒绝,则返回一个拒绝状态的 Promise 实例,并返回一个聚合了所有拒绝原因的 AggregateError 对象。

以下是一个使用 Promise.any 的示例,假设我们有两个 Promise 实例:

const p1 = new Promise((resolve) => setTimeout(resolve, 1000, 'Promise 1'));
const p2 = new Promise((resolve, reject) => setTimeout(reject, 500, 'rejected'));

我们将它们传入 Promise.any,并通过 then 方法和 catch 方法分别处理成功解析和拒绝的情况:

Promise.any([p1, p2])
  .then((result) => console.log(result))
  .catch((reasons) => console.error(reasons));

在上面的示例中,由于 p1 在 1 秒后成功解析,而 p2 在 500 毫秒后被拒绝,所以 Promise.any 将返回一个已解析的 Promise 实例,并将 'Promise 1' 作为结果输出。如果我们将 p2 的延迟时间增加到 1500 毫秒,那么 Promise.any 将返回一个被拒绝的 Promise 实例,并返回一个包含拒绝原因的 AggregateError 对象。例如:

const p1 = new Promise((resolve) => setTimeout(resolve, 1000, 'Promise 1'));
const p2 = new Promise((resolve, reject) => setTimeout(reject, 1500, 'rejected'));

Promise.any([p1, p2])
  .then((result) => console.log(result))
  .catch((reasons) => console.error(reasons));

在上面的示例中,由于 p1 在 1 秒后成功解析,而 p2 在 1.5 秒后被拒绝,所以 Promise.any 将返回一个被拒绝的 Promise 实例,并返回一个包含 'rejected' 被拒绝原因的 AggregateError 对象。

需要注意的是,Promise.any 并不是所有浏览器和运行时环境都支持的,因此在使用时需要确认目标环境的支持情况。如果你需要在不支持 Promise.any 的环境中使用它,可以通过使用 npm 或类似的工具(如 core-js)来添加对 Promise.any 方法的 polyfill 支持。

补充知识点:

Promise.all、Promise.race、Promise.any的区别

all: 成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值

race: 哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

any: 返回最快的成功结果,如果全部失败就返回失败结果。

实际上 Promise.race 和 Promise.all 方法的参数可以是任何类型,包括数字、字符串等基本类型和对象、函数等引用类型。

在传递给 Promise.race 方法的 Promise 实例数组中,当数组元素不是 Promise 实例时,会自动将该元素包装成为一个 Promise 实例并被立即采用其状态。

例如,当传递一个包含数字、布尔值、字符串等基本类型的数组时,它们会被包装成 Promise 实例,立即采用其解析状态,并将解析的结果作为输出结果。

Promise.race([1, true, 'Hello'])
  .then(result => console.log(result))
  .catch(reasons => console.error(reasons)); // 输出 1

在上述示例中,传递给 Promise.race 方法的 Promise 实例数组中包含了数字 1、布尔值 true 和字符串 ‘Hello’,它们被自动包装为 Promise 对象并立即被解析,而它们的值也直接被返回。因为数字 1 是数组中的第一个元素,所以即便传递了多个参数,Promise.race 方法也只会采用它的状态。

再看另一个例子,在传递一个包含多种类型的引用类型的数组时,会对数组元素调用 Promise.race 方法,以其返回值作为处理结果:

const p1 = new Promise(resolve => setTimeout(resolve, 1000, 'first'));
const p2 = new Promise(resolve => setTimeout(resolve, 500, 'second'));
const p3 = { x: 123 };
const p4 = () => 'function';

Promise.race([p1, p2, p3, p4])
  .then(result => console.log(result))
  .catch(reasons => console.error(reasons)); // 输出 { x: 123 }

在上述示例中,传递给 Promise.race 方法的数组包含了两个 Promise 实例 p1、p2,一个对象字面量 { x: 123 },和一个具有返回值的普通函数,在 Promise.race 方法调用时,会同时调用这些元素,并采用第一个状态改变的元素的状态。因为对象字面量和函数都是引用类型,Javascript 引擎会在这里将其转换为 Promise 对象并返回。

因此,虽然 Promise.race 和 Promise.all 方法主要用来处理多个 Promise 实例的并发场景,但实际上它们对所有数据类型都具有通用性,并且可以轻松处理任何类型的元素数组。

转载自:https://juejin.cn/post/7241842830889189434
评论
请登录