《深入浅出node.js》Promise/Deferred部分读
最近在用node.js写一个工具,发现自己对Promise的模式还是不太了解,于是打算重温《深入浅出node.js》,不过精读的时候发现该书没有随书代码的下载,而且书中关于Promise的部分代码交代不够清楚,可能影响读者理解,本人花了一些时间将代码整理出来,建议读者对照书籍查看。
1.Promise/A
不清楚Promise模式定义的同学请自行百度,书中使用Promise/A模式以点带面介绍Promise。在介绍完Promise/A的抽象定义后,通过继承node的events模块来完成了一个简单的实现。
![](https://img.haomeiwen.com/i934623/2a664e28bf0185b0.png)
需要注意两点 :
1)Promise继承自events,其中继承的方式采用了寄生组合式继承(详见《Javascript高级程序设计》第三版)
2)then方法继续返回Promise对象,以实现链式调用
为了完成整个流程,还需要触发执行这些回调函数的地方,实现这些功能的对象通常被称为Deferred,即延迟对象
![](https://img.haomeiwen.com/i934623/c2150fc01f59a6db.png)
现在我们对一个典型的响应对象进行封装
![](https://img.haomeiwen.com/i934623/fc4df680fa55021d.png)
我们将其改造为Promise/A模式
![](https://img.haomeiwen.com/i934623/32943ecea9ffb2b2.png)
![](https://img.haomeiwen.com/i934623/ab9e8c48847c78b8.png)
原书在18行代码出有错误,已调整。。从上面的代码可以看出,Deferred主要是用于内部,用于维护异步模型的状态;Promise则作用于外部,通过then()方法暴露给外部以添加自定义逻辑。
2.Promise中的多异步协作
在Promise的介绍中说过,主要解决的是单个异步操作中存在的问题。回到我们的难点,当我们需要处理多个异步调用时,又该如何处理呢?
这里我们保持Promise代码不变
![](https://img.haomeiwen.com/i934623/3bab2cb86b465471.png)
Deferred代码增加了all()方法,all()方法将两个单独的Promise重新抽象组合成一个新的Promise
![](https://img.haomeiwen.com/i934623/139c745355602792.png)
![](https://img.haomeiwen.com/i934623/f8b98413793029e9.png)
我们以多次访问文件为例,只有所有异步操作成功,这个异步操作才算成功,一旦其中一个异步操作失败,整个异步操作就失败。
![](https://img.haomeiwen.com/i934623/085528d8b017c0af.png)
3.Promise的同步操作
在Node中,网络库是完全异步的,无法在编程层面实现像其他语言那般的同步调用。因此解决同步调用的代码可能就变成了
![](https://img.haomeiwen.com/i934623/dd5999745bbe3563.png)
理想的编程体验应当是前一个的调用结果作为下一个调用的开始,是传说中的链式调用,下面进行改造
Promise代码:
![](https://img.haomeiwen.com/i934623/bfa4cc4cee606a28.png)
Deferred代码:
![](https://img.haomeiwen.com/i934623/65a660ffaa657238.png)
![](https://img.haomeiwen.com/i934623/60e9a94df61ed654.png)
调用代码:
![](https://img.haomeiwen.com/i934623/020f60d3636c25bd.png)
![](https://img.haomeiwen.com/i934623/d1dd0fc57b438bd5.png)
可以看到最后一个then的调用主体已经完全转交给了readFile2中的promise对象,通过这种方式,我们完全可以写出更优雅的同步代码。