2

Promise.race() 原理解析及使用指南

 2 years ago
source link: https://my.oschina.net/lav/blog/5233697
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Promise 对象是 ECMAScript 6 中新增的对象,主要将 JavaScript 中的异步处理对象和处理规则进行了规范化。前面介绍了《Promise.any() 原理解析及使用指南》、《Promise.all() 原理解析及使用指南》和《Promise.allSettled() 原理解析及使用指南》,本文继续来介绍 Promise 另一个方法 Promise.race(promises) ,顾名思义就是赛跑的意思,Promise.race([p1, p2, p3]) 里面 promise 数组那个执行完成得快就获取那个的结果,不管结果本身是成功履行状态还是失败拒绝状态,只输出最快的 promise

下面来看看 Promise.race() 是如何工作的。

1.工作原理

Promise.race() 返回一个 promise,一旦迭代器中的某个 promise 履行或拒绝,返回的 promise 就会履行或拒绝。

函数接受一个 promise 数组(或通常是一个可迭代的)作为参数,如下:

const racePromise = Promise.race(promises);

当所有输入 promises 中有一个 promise 快速被履行或拒绝时,racePromise 就会解析快速完成的 promise 结果(履行或拒绝):

可以使用 then 方法提取 racePromise 的结果:

racePromise.then((fastValue) => {
    fastValue // 快速完成的 promise
});

也可以使用 async/await 语法:

const fastPromise = await racePromise;

fastPromise; //  快速完成的 promise

Promise.race() 返回的承诺和最先完成的承诺信息一致。

Promise.race()Promise.any() 的不同:Promise.race() 承诺列表中寻找第一个履行或拒绝的承诺;Promise.any() 是从承诺列表中查找第一个履行的承诺。

2. 使用指南

现在来深入介绍 Promise.race() 的使用之前,同样先来定义 2 个简单的函数。

function resolveTimeout(value, delay) {
    return new Promise((resolve) => setTimeout(() => resolve(value), delay));
}
function rejectTimeout(reason, delay) {
    return new Promise((r, reject) => setTimeout(() => reject(reason), delay));
}

接下来使用上面定义的2个辅助函数来试试 Promise.race()

2.1 完成所有 promises

下面定义了一个 promise 数组 racePromise ,所有的 promise 都能够成功的 resolve 值,如下:

const fruits = ["potatoes", "tomatoes"];
const vegetables = ["oranges", "apples"];

const racePromise = Promise.race([
    resolveTimeout(fruits, 5000),
    resolveTimeout(vegetables, 1000),
]);

// 等待 1 秒 ...
const list = async () => {
    try {
        const fastPromise = await racePromise;
        console.log(fastPromise);
    } catch (error) {
        console.log(error);
    }
};

list(); // [ 'oranges', 'apples' ]

从上面执行的结果来看 Promise.race() 返回最快履行的 promiseresolve 结果。

2.2 一个 promiserejected

将上面第一个 promise 出现异常被 rejected ,如下代码:

const fruits = ["potatoes", "tomatoes"];

const racePromise = Promise.race([
    resolveTimeout(fruits, 2000),
    rejectTimeout(new Error("Vegetables is empty"), 1000),
]);

// 等待 1 秒 ...
const list = async () => {
    try {
        const fastPromise = await racePromise;
        console.log(fastPromise);
    } catch (error) {
        console.log(error);
    }
};

list(); // Error: Vegetables is empty

从上面的结果看,最先完成的 promiserejected ,那么 fastPromise 返回的 promise 也是被 rejected

下面将rejected 的承诺时间延长到 5秒,如下:

const fruits = ["potatoes", "tomatoes"];

const racePromise = Promise.race([
    resolveTimeout(fruits, 2000),
    rejectTimeout(new Error("Vegetables is empty"), 5000),
]);

// 等待 2 秒 ...
const list = async () => {
    try {
        const fastPromise = await racePromise;
        console.log(fastPromise);
    } catch (error) {
        console.log(error);
    }
};

list(); // [ 'potatoes', 'tomatoes' ]

从上面执行结果看到,最快完成的 promise 履行了 resolve ,那么 fastPromise 返回的 promise 也是履行了 resolve

2.3 所有 promisesrejected

将上面所有的 promises 出现异常被 rejected ,如下代码:

const racePromise = Promise.race([
    rejectTimeout(new Error("Fruits is empty"), 2000),
    rejectTimeout(new Error("Vegetables is empty"), 1000),
]);

// 等待 1 秒 ...
const list = async () => {
    try {
        const fastPromise = await racePromise;
        console.log(fastPromise);
    } catch (error) {
        console.log(error);
    }
};

list(); // Error: Vegetables is empty

从结果来看,虽然两个承诺都被拒绝了,fastPromise 返回的 promise 是最快被拒绝的 。

3. 使用场景

3.1. 性能测试

在有异步操作的项目中,在对于网络或数据库请求进行性能进行优化的时候,可以使用 Promises 来测试其优化效果,通过使用 Promise.race() 来测试两种不同的方法的响应速度。

3.2 最佳选择

例如获取同一类型的数据有多个请求服务器,同时向多个服务器发送请求,只要其中一个完成工作,就将其数据呈现,达到选择最佳线路的效果。这是可以使用 Promise.race() 同时执行 promise 并在第一个成功后立即完成。

文章介绍了 Promise.race() 原理和使用,另外增加了2个可能用得到的场景,而Promise.race()Promise.any() 之间的基本区别在于,Promise.race() 为第一个已解决和已拒绝的 promise 执行回调函数,而 Promise.any() 为第一个已履行的 promise 执行回调函数,如果没有履行的 promise 则拒绝一个特殊属性 AggregateError


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK