NodeJS 异步 API 允诺化
正文之前,我们先阐明几个概念:
- 允诺(Promise):想必不需要解释。这个概念貌似缺乏一个约定俗成的中文翻译,这里就现造一个罢。
- 允诺式(Promisive):基于允诺的异步编程方式,包括允诺链和异步函数等;一个对立面是回调式。
- 允诺化(Promisify):将非允诺式的程序或 API 转化为允诺式。
引子
允诺(Promise)是现代异步编程的基础与核心,而 NodeJS 的设计早于允诺。 因此,其大量的异步 API 皆为回调式。不进行允诺化(Promisify)改造,我们就无法方便地使用。 理想情况是官方修改这些 API 的行为,当没有回调函数传入时,返回一个允诺。 然而这取决于官方的态度,由于这将破坏向后兼容,他们自然是要周全考虑,不可能轻易改动。 作为普通用户,我们只有自己动手了。
一个方案是将需要用的 API 进行再次封装,鉴于异步 API 庞大的数量, 我们只能用到哪些封装哪些。但这并不令人满意。当我们用到新的 API 又得重新封装; 并且,我们被迫要额外记忆封装后的另一套 API;每个项目,每个开发者,又有不同的封装方案。
最好是能用一个精简的方式构造一个通用的解决方案。比如如下的方案:
定义
用法:
设计思路
分析 NodeJS 的异步 API 规范为:不论接受几个参数,最后一个参数为回调函数, 并且回调函数所接受的第一个参数统一为错误,第二个参数为接口的响应。 据此设计通用的 Do 函数。
Do 函数的用法略显别扭。如果我们只使用某个模块中的异步函数,就可将整个模块允诺化,
提供更顺手的 API。可以使用一个原模块的代理(Proxy)对象,拦截接口的访问,
并返回封装层,通过 Do 函数访问接口。这里对封装层作了缓存,目的是使每一次访问都获取到同一个函数,
避免出现 pfs.readFile !== pfs.readFile
的诡异现象。