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();
}
};
由于 async
和 await
绝对更好,我们仍然建议使用它们而不是普通 Promise。也就是说,如果您出于某种原因更喜欢普通 Promise,Promise.prototype.finally
可以帮助您使代码更简单、更清晰。
Promise.prototype.finally
支持 #
- Chrome: 从版本 63 开始支持
- Firefox: 从版本 58 开始支持
- Safari: 从版本 11.1 开始支持
- Node.js: 从版本 10 开始支持
- Babel: 支持