背景
在前端开发中,Promise 是很常见的异步编程解决方案。它的出现让我们可以更便捷地处理异步操作,但是在过去的版本中,Promise 还存在一些烦人的问题,比如:
- 处理不当会导致 unhandled rejection 错误
- 是否成功都必须执行的某些代码很难维护
对于第二个问题,Promise.prototype.finally() 的出现为我们解决了这个问题。
Promise.prototype.finally()
Promise.prototype.finally() 是 ES10 新增的方法,它接受一个回调函数作为参数,该回调函数在 Promise 被 resolve 或 reject 后都会调用,无论 Promise 最后的状态是成功还是失败,也无论是否有 finally 回调函数注册。
Promise.prototype.finally = function(onFinally) { return this.then( result => Promise.resolve(onFinally()).then(() => result), reason => Promise.resolve(onFinally()).then(() => { throw reason }) ); };
其内部实现是通过 Promise.resolve() 包装回调函数,并 Promise 链式调用 then() 方法,使得代码更加简洁明了。我们可以通过 Promise.prototype.finally() 实现清理资源、关闭网络连接等操作,而且不用担心它会影响 Promise 最终的状态。
应用场景
提供统一的处理逻辑
Promise.prototype.finally() 为 Promise 提供了一种处理成功和失败的方式,能够自动执行后续代码,避免了回调地狱。另外,它还可以用于提供统一的处理逻辑,比如:
function fetchApi() { return fetch('/api/v1/data') .then(response => response.json()) .catch(error => { throw error; }) .finally(() => { console.log('API request done.'); }); }
在上面的代码中,我们定义了一个 fetchApi() 函数,并在 Promise 函数链中通过 .finally() 注册了一个回调函数,用于在 fetch 接口请求完成后显示一条消息。
清理资源
function downloadFile(url) { return fetch(url) .then(response => response.blob()) .finally(() => window.URL.revokeObjectURL(url)) // 清理资源 .then(blob => { ... }); }
在上面的代码中,我们定义了一个 downloadFile() 函数用于下载文件,并在 fetch().finally() 函数链中带有资源清理逻辑,用于释放占用的内存和更新 GUI 界面。
关闭网络连接
function closeConnection() { return new Promise((resolve, reject) => { const socket = new WebSocket('ws://localhost:3000'); socket.onopen = () => resolve(socket); socket.onclose = () => console.log('Socket connection has been closed.'); }) .finally(() => socket.close()); // 关闭网络连接 }
在上面的代码中,我们定义了一个 closeConnection() 函数来关闭 Websocket 网络连接,其中通过 Promise 封装 Websocket 连接,.finally() 注册了一个回调函数来关闭网络连接。
总结
Promise.prototype.finally() 可以使我们更好地处理 Promise 的逻辑,排除一些不必要的麻烦,同时也可以提高代码的清晰度和可读性。在网页开发中,我们会遇到很多异步操作,使用 Promise.prototype.finally() 改进代码逻辑可以使代码更加清晰易读。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65966ccfeb4cecbf2da3fc9a