图解 JavaScript:Promises
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
在学习 JavaScript 和编程的过程中,我发现用类比的方式来理解概念很有帮助。这里我将分享一个关于 JavaScript 中 Promise 的类比。欢迎在评论区补充。
在 JavaScript 中,如果我们想在异步函数返回后才调用另一个函数,可以使用回调函数。假设我正在烤一个巧克力糖霜蛋糕,那么我的bakeCake()函数是异步的,它接受prepareIcing()一个参数(这就是回调函数),并且只有在蛋糕完全烤好后才会调用它。
但本文我们将重点讨论如何使用Promise。那么 Promise 如何帮助我们解决这个问题呢?Promise 是一个封装了异步操作的对象,如果操作成功,它会被赋值;如果操作失败,它会被拒绝并返回一个原因。这样,我就可以为某个未来才会出现的值(或原因)添加一个处理程序。
回到烘焙的例子,我可以说我的烤箱就像一个蛋糕的承诺,因为它封装了我的烘焙蛋糕操作,并且一开始处于待处理状态(仍在烘焙)。但我有一个智能烤箱,它会在操作完成后通知我。如果烘焙成功,承诺就会兑现,得到一个蛋糕。否则,承诺就会被拒绝,并显示蛋糕烤焦或其他失败原因。
正如我们之前所说,使用 Promise,我们可以为其最终状态(成功或失败)添加处理程序。该.then()方法可以同时处理成功和失败(失败的情况较少见),而该.catch()方法只能处理失败。
如果我要烤一个简单的蛋糕(不加糖霜),我会这样处理:如果成功了,我就把蛋糕端上桌。但如果烤糊了,我可以把失败的蛋糕捡起来扔进垃圾桶,然后点个派当甜点。😂
另一点需要注意的是,由于一个 Promise 会返回另一个 Promise,因此它们可以链式调用。在我之前提到的蛋糕加糖霜的例子中,我可以先烤好蛋糕,然后准备糖霜,最后蛋糕和糖霜都准备好后,再给蛋糕涂上糖霜。在这种情况下,如果链中的任何一个 Promise 失败,我只需处理一次catch 语句就能处理所有拒绝,然后继续订购一个派。
但有一种更好的方法可以实现我们在上一个例子中所做的操作。我bakeCake()的两个prepareIcing()函数是独立的,这意味着它们可以同时执行。为此,我们可以使用Promise.all()等待两个结果(蛋糕和糖霜)都得到后再执行coverCake()函数。
在内部Promise.all(),如果其中任何一个承诺被拒绝(失败),那么整个承诺都会被拒绝。这很合理,对吧?如果蛋糕或糖霜缺失,我就无法盖住整个蛋糕。
以上是对 Promise 概念及其使用方法的非常简化和概括的解释。.then()希望足够清晰易懂。.catch()Promise.all()
感谢阅读,欢迎在评论区留言。我保证下一篇文章已经在酝酿中了(待定)。完成后我会第一时间在推特上分享,如果被拒稿,我就发些猫咪照片。
本文要点:
- Promise 是封装异步操作的对象。
- 承诺始于待定状态,在未来的某个时刻,它们会变为已履行(成功)或已拒绝(失败)状态。
- Promise 会返回一个新的 Promise,该 Promise 可以用于链式调用。
.then()我们可以使用`or`在操作返回时为成功值或失败原因添加处理程序.catch()。Promise.all()等待所有承诺都得到解决。如果任何承诺被拒绝,则该承诺被拒绝。
参考文献和推荐延伸阅读
- 图解JS:JavaScript异步行为
- Marijn Haverbeke 使用 Eloquent JavaScript 进行异步编程
- 在 MDN Web 文档中使用 Promise





