Promise.all()使用场景

在上一节我们介绍了Promise.all()典型的两类使用场景,今天我们再看看另一类:
创建人为的延迟
Promise.all() 的一个不太常见的场景是当你想延迟某件发生太快的事情。 这更有可能发生在浏览器而不是服务器端,您有时需要在用户操作和响应之间稍作延迟。 例如,您可能希望在从服务器获取数据时显示加载指示器,但如果响应太快,用户可能看不到加载微调器,因此不知道屏幕上的数据是最新的。 在这种情况下,您可以引入人为的延迟,如下所示:
const API_BASE = "https://jsonplaceholder.typicode.com";
const appElement = document.getElementById("app");
function delay(milliseconds) {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, milliseconds);
});
}
function fetchUserData(userId) {
appElement.classList.add("loading");
const urls = [
`${API_BASE}/users/${userId}/posts`,
`${API_BASE}/users/${userId}/albums`
];
return Promise.all([
...urls.map(url => fetch(url)),
delay(1500)
]).then(results => {
// strip off the undefined result from delay()
return results.slice(0, results.length - 1);
});
}
fetchUserData(1).then(responses => {
return Promise.all(
responses.map(
response => {
if (response.ok) {
return response.json();
} else {
return Promise.reject(
new Error(`Unexpected status code: ${response.status} ${resp\
onse.statusText} for ${response.url}`)
);
}
}
)
);
}).then(([posts, albums]) => {
// process your data as necessary
console.log(posts);
console.log(albums);
}).finally(() => {
appElement.classList.remove("loading");
}).catch(reason => console.error(reason.message));
此代码通过在每个 fetch() 调用中引入延迟来构建前面的示例。 delay() 函数返回一个promise,该promise会在指定的毫秒数过去后resolve。 它通过使用本机 setTimeout() 函数并传递调用 resolve() 的回调函数。请注意,在这种情况下不需要向 resolve() 传递任何值,因为没有相关数据。
您也可以直接将 resolve 作为第一个参数传递给 setTimeout(); 但是,一些 JavaScript 运行时将参数传递给超时回调。 为了在运行时之间获得最佳兼容性,最好从另一个函数内部调用 resolve()。
fetchUserData() 函数启动指定用户 ID 的 Web 服务请求。与上一节的示例一样,Promise.all() 用于监控多个 fetch() 请求,但 在这个例子中,传递给 Promise.all() 的数组中还包含对 delay() 的调用。当返回的promise fullfiled时,fullfilment handler接收所有结果的数组,包括作为最后一个数组元素的未定义。在从 fetchUserData() 返回之前,最后一个元素被删除,因此调用 fetchUserData() 的代码根本不需要知道 delay() 调用。 CSS 类加载被添加到 DOM 中的应用程序元素中,以指示正在检索数据,然后在收到响应时由settlement handler删除。
您刚刚学习了使用 Promise.all() 的用例最佳解决方案。但如果你想要即使一个promise rejected,您的操作还会继续吗?这就是 Promise.allSettled() 是更好的选择。