摘要:在本教程中,您将学习如何使用 JavaScript Promise.race()
静态方法。
JavaScript Promise.race() 静态方法简介
Promise.race()
静态方法接受一个包含 promise 的可迭代对象,并返回一个新的 promise。该 promise 一旦其中一个 promise fulfilled 或 reject,就会立即 fulfilled 或 reject,并带有该 promise 的值或原因。
以下是 Promise.race()
方法的语法
Promise.race(iterable)
Code language: JavaScript (javascript)
在此语法中,iterable
是一个 可迭代对象,包含一个 promise 列表。
Promise.race()
的名称暗示所有 promise 彼此竞争,只有一个赢家,无论成功还是失败。
请参见以下图表
在这个图表中
promise1
在t1
时用值v1
fulfilled。promise2
在t2
时用error
reject。- 由于
promise1
比promise2
提前完成,promise1
获胜。因此,Promise.race([promise1, promise2])
返回一个新的 promise,该 promise 在t1
时用值v1
fulfilled。
请参见另一个图表
在这个图表中
promise1
在t2
时用v1
fulfilled。promise2
在t1
时用error
reject。- 由于
promise2
比promise1
提前完成,promise2
获胜。因此,Promise.race([promise1, promise2])
返回一个新的 promise,该 promise 在t1
时用error
reject。
JavaScript Promise.race() 示例
让我们来看一些使用 Promise.race()
静态方法的示例。
1) 简易 JavaScript Promise.race() 示例
以下代码创建了两个 promise:一个在 1 秒后完成,另一个在 2 秒后完成。由于第一个 promise 比第二个 promise 完成得快,Promise.race()
用第一个 promise 的值完成。
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('The first promise has resolved');
resolve(10);
}, 1 * 1000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('The second promise has resolved');
resolve(20);
}, 2 * 1000);
});
Promise.race([p1, p2])
.then(value => console.log(`Resolved: ${value}`))
.catch(reason => console.log(`Rejected: ${reason}`));
Code language: JavaScript (javascript)
输出
The first promise has resolved
Resolved: 10
The second promise has resolved
以下示例创建了两个 promise。第一个 promise 在 1 秒后完成,而第二个 promise 在 2 秒后失败。由于第一个 promise 比第二个 promise 快,返回的 promise 用第一个 promise 的值完成。
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('The first promise has resolved');
resolve(10);
}, 1 * 1000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('The second promise has rejected');
reject(20);
}, 2 * 1000);
});
Promise.race([p1, p2])
.then(value => console.log(`Resolved: ${value}`))
.catch(reason => console.log(`Rejected: ${reason}`));
Code language: JavaScript (javascript)
输出
The first promise has resolved
Resolved: 10
The second promise has rejected
请注意,如果第二个 promise 比第一个 promise 快,返回的 promise 就会因为第二个 promise 的原因而失败。
2) 实际 JavaScript Promise.race() 示例
假设您需要在从服务器加载数据时显示一个加载指示器,如果加载时间超过一定秒数。
为此,您可以使用 Promise.race()
静态方法。如果发生超时,您显示加载指示器,否则,您显示消息。
以下示例说明了 HTML 代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript Promise.race() Demo</title>
<link href="css/promise-race.css" rel="stylesheet">
</head>
<body>
<div id="container">
<button id="btnGet">Get Message</button>
<div id="message"></div>
<div id="loader"></div>
</div>
<script src="js/promise-race.js"></script>
</body>
</html>
Code language: HTML, XML (xml)
为了创建加载指示器,我们使用 CSS 动画功能。有关更多信息,请参见 promise-race.css
。从技术角度而言,如果元素具有 .loader
类,则它会显示加载指示器。
首先,定义一个用于加载数据的函数。它使用 setTimeout()
模拟异步操作
const DATA_LOAD_TIME = 5000;
function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const message = 'Promise.race() Demo';
resolve(message);
}, DATA_LOAD_TIME);
});
}
Code language: JavaScript (javascript)
其次,开发一个用于显示某些内容的函数
function showContent(message) {
document.querySelector('#message').textContent = message;
}
Code language: JavaScript (javascript)
该函数还可用于将 message
设置为空。
第三,定义 timeout()
函数,该函数返回一个 promise。当指定的 TIMEOUT
超时时,该 promise 将被拒绝。
const TIMEOUT = 500;
function timeout() {
return new Promise((resolve, reject) => {
setTimeout(() => reject(), TIMEOUT);
});
}
Code language: JavaScript (javascript)
第四,开发两个函数,用于显示和隐藏加载指示器
function showLoadingIndicator() {
document.querySelector('#loader').className = 'loader';
}
function hideLoadingIndicator() {
document.querySelector('#loader').className = '';
}
Code language: JavaScript (javascript)
第五,向获取消息按钮附加一个点击事件监听器。在点击处理程序内,使用 Promise.race()
静态方法
// handle button click event
const btn = document.querySelector('#btnGet');
btn.addEventListener('click', () => {
// reset UI if users click the 2nd, 3rd, ... time
reset();
// show content or loading indicator
Promise.race([getData()
.then(showContent)
.then(hideLoadingIndicator), timeout()
])
.catch(showLoadingIndicator);
});
Code language: JavaScript (javascript)
我们将两个 promise 传递给 Promise.race()
方法
Promise.race([getData()
.then(showContent)
.then(hideLoadingIndicator), timeout()
])
.catch(showLoadingIndicator);
Code language: JavaScript (javascript)
第一个 promise 从服务器获取数据,显示内容,并隐藏加载指示器。第二个 promise 设置一个超时。
如果第一个 promise 需要超过 500 毫秒才能完成,则调用 catch()
来显示加载指示器。第一个 promise 完成后,它会隐藏加载指示器。
最后,开发一个 reset()
函数,如果按钮被第二次点击,则隐藏消息和加载指示器。
// reset UI
function reset() {
hideLoadingIndicator();
showContent('');
}
Code language: JavaScript (javascript)
将所有内容组合在一起。
// after 0.5 seconds, if the getData() has not resolved, then show
// the Loading indicator
const TIMEOUT = 500;
const DATA_LOAD_TIME = 5000;
function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const message = 'Promise.race() Demo';
resolve(message);
}, DATA_LOAD_TIME);
});
}
function showContent(message) {
document.querySelector('#message').textContent = message;
}
function timeout() {
return new Promise((resolve, reject) => {
setTimeout(() => reject(), TIMEOUT);
});
}
function showLoadingIndicator() {
document.querySelector('#loader').className = 'loader';
}
function hideLoadingIndicator() {
document.querySelector('#loader').className = '';
}
// handle button click event
const btn = document.querySelector('#btnGet');
btn.addEventListener('click', () => {
// reset UI if users click the second time
reset();
// show content or loading indicator
Promise.race([getData()
.then(showContent)
.then(hideLoadingIndicator), timeout()
])
.catch(showLoadingIndicator);
});
// reset UI
function reset() {
hideLoadingIndicator();
showContent('');
}
Code language: JavaScript (javascript)
总结
Promise.race(iterable)
方法返回一个新的 promise,该 promise 一旦可迭代对象中的一个 promise fulfilled 或 reject,就会立即 fulfilled 或 reject,并带有该 promise 的值或错误。