Promise.prototype.finally

发布时间 · 标签:ECMAScript ES2018

Promise.prototype.finally 允许注册一个回调函数,该函数将在 Promise 完成(即 fulfilled 或 rejected)时被调用。

想象一下,您想获取一些数据并在页面上显示。此外,您希望在请求开始时显示一个加载动画,并在请求完成后隐藏它。如果出现错误,则显示错误消息。

const fetchAndDisplay = ({ url, element }) => {
showLoadingSpinner();
fetch(url)
.then((response) => response.text())
.then((text) => {
element.textContent = text;
hideLoadingSpinner();
})
.catch((error) => {
element.textContent = error.message;
hideLoadingSpinner();
});
};

fetchAndDisplay({
url: someUrl,
element: document.querySelector('#output')
});

如果请求成功,我们将显示数据。如果出现错误,我们将显示错误消息。

无论哪种情况,我们都需要调用 hideLoadingSpinner()。到目前为止,我们别无选择,只能在 then()catch() 块中重复此调用。使用 Promise.prototype.finally,我们可以做得更好。

const fetchAndDisplay = ({ url, element }) => {
showLoadingSpinner();
fetch(url)
.then((response) => response.text())
.then((text) => {
element.textContent = text;
})
.catch((error) => {
element.textContent = error.message;
})
.finally(() => {
hideLoadingSpinner();
});
};

这不仅减少了代码重复,而且更清晰地将成功/错误处理阶段和清理阶段分隔开来。太棒了!

目前,使用 async/await 可以实现相同的效果,而无需 Promise.prototype.finally

const fetchAndDisplay = async ({ url, element }) => {
showLoadingSpinner();
try {
const response = await fetch(url);
const text = await response.text();
element.textContent = text;
} catch (error) {
element.textContent = error.message;
} finally {
hideLoadingSpinner();
}
};

由于 asyncawait 绝对更好,我们仍然建议使用它们而不是普通 Promise。也就是说,如果您出于某种原因更喜欢普通 Promise,Promise.prototype.finally 可以帮助您使代码更简单、更清晰。

Promise.prototype.finally 支持 #