别再硬推 async/await 了
Promise 现在可火了
自盘古开天辟地以来,开发者们就一直在进行各种愚蠢的争论。从经典的”制表符 vs. 空格”到永恒的”Mac vs. PC”辩论,我们很擅长寻找分散注意力的论点。
答案: Linux 和 Spaces.
这场争论……?
Promise vs. Async/Await!
等等,这是一场争论吗?肯定是吧?我们似乎不再讨论回调函数了?
不,这不是一场争论。归根结底,它只是你工具箱中的另一个潜在工具。然而,由于 async/await 并未取代 Promise 的所有功能(特别是 Promise.all、.race),将其作为替代品来呈现是具有误导性的。
有很多有影响力的人正在推广这种误解,即 async/await 是 Promise 的替代品每个人一直等待的。
提示:不,绝不,一点也不。
VS Code 最近新增的一个功能进一步助长了这种偏见。正如 @umaar 在推文中所述:
Visual Studio Code 现在可以将你的长串 Promise.then() 链转换为 async/await!🎊 在 JavaScript 和 TypeScript 文件中都运行良好。.catch() 也能正确转换为 try/catch ✅ pic.x.com/xb39Lsp84V
— Umar Hansa (@umaar) 2018年9月28日
如果你讨厌 Promise,并且想要这个重构功能,我不怪你。
我感同身受。我理解。
我也经历过。🤗
我过去讨厌 Promise。如今,我彻底转变了看法。Promise 非常出色。 它们能够促使/鼓励你利用函数组合。
我建议先从以下两个方面入手,提升你的 Promise 技巧。
#1:命名函数!
干掉你的匿名方法。使用命名函数能让代码读起来像需求的诗歌。
来看一个常见例子:
使用 fetch 发起 HTTP GET 请求:
反模式
// ❌ 使用匿名内联函数 💩fetch(url) .then(response => response.status < 400 ? response : Promise.reject(new Error('Request Failed: ' + response.ststus))) .then(response => response.text())解决方案:命名方法
// ✅ 清晰显现:命名函数fetch(url) .then(checkResponse) .then(getText)
// 可复用的通用函数function checkResponse(response) { return response.status < 400 ? response : Promise.reject(new Error('Request Failed: ' + response.ststus))}function getText(response) { return response.text()}随着代码越来越 DRY,这种方法的优势会愈发明显。
额外资源: 查看我的 1 分钟视频,演示使用此技术的基础日志和高级调试。
#2:单一职责(函数)
“单一职责”听起来_看似精确_。
但它其实非常主观、随意,甚至有时毫无意义。
让我们看一个例子,这个例子来自(才华横溢的)Jake Archibald 在 Google Developers 网站上关于 async/await 的文章(注意:2024 年,链接已移除)。
// 来源:https://developers.google.com/web/fundamentals/primers/async-functionsfunction logInOrder(urls) { // 获取所有 URL const textPromises = urls.map(url => { return fetch(url).then(response => response.text()); });
// 按顺序记录它们 textPromises.reduce((chain, textPromise) => { return chain.then(() => textPromise) .then(text => console.log(text)); }, Promise.resolve());}单一职责?
我认为不是。logInOrder 在做什么?
- 遍历
urls列表 - 对每个 URL 执行内联 HTTP GET:
- HTTP
fetch - 返回响应文本内容
- 在
textPromise中的每个 promise 后追加一个.then(text => console.log(text)) - 串行打印结果
这个单一函数中定义了 5 个匿名方法。正如 Jake 所指出的,.reduce 过于复杂。在代码中到处手写这种精细机制并不合理。换句话说,我们不会用无尽的 document.createElement()、element.setAttribute() 等来编写 DOM 创建代码。相反,我们会从众多选项中选择最佳工具:辅助/工具函数、库或框架。
解决方案:单一职责函数
首先提取方法…

接着用 Promise.all 和 ..map() 替换 .reduce() 和 logPromise()…

总结
尝试将这些技巧应用到自己的代码中!然后在推特上@我,告诉我效果如何。如果有问题或评论,也欢迎联系我!
帮助传播 #PromiseTruth 并分享本文。❤️
