假设您维护一个公开函数的库getData
。您的用户调用它来获取实际数据:
var output = getData();
幕后数据保存在一个文件中,因此您getData
使用 Node.js 内置fs.readFileSync
. 很明显这两个getData
和fs.readFileSync
是同步的功能。有一天,您被告知将底层数据源切换到只能异步访问的存储库,例如 MongoDB。您还被告知要避免激怒您的用户,getData
API 不能更改为仅返回Promise或要求回调参数。你如何满足这两个要求?
使用回调/Promise的异步函数是 JavasSript 和 Node.js 的 DNA。任何非平凡的 JS 应用程序都可能渗透这种编码风格。但这种做法很容易导致所谓的厄运回调金字塔。更糟糕的是,如果调用链中任何调用方的任何代码都依赖于异步函数的结果,那么这些代码也必须包装在回调函数中,从而对调用方施加编码风格约束。有时我发现需要将异步函数(通常在 3rd 方库中提供)封装到同步函数中,以避免大规模的全局重构。寻找有关此主题的解决方案通常以Node Fibers告终或从它派生的 npm 包。但是 Fibers 无法解决我面临的问题。即使是 Fibers 的作者提供的例子也说明了缺陷:
...
Fiber(function() {
console.log('wait... ' + new Date);
sleep(1000);
console.log('ok... ' + new Date);
}).run();
console.log('back in main');
实际输出:
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
如果函数 Fiber 真的将异步函数 sleep 变为同步,则输出应该是:
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
back in main
我在JSFiddle 中创建了另一个简单的例子,并寻找产生预期输出的代码。我会接受一个仅适用于 Node.js 的解决方案,因此您可以自由地要求任何 npm 包,尽管不在 JSFiddle 中工作。