假设您维护一个公开函数的库getData
。您的用户调用它来获取实际数据:
var output = getData();
在后台数据保存在一个文件中,因此您getData
使用 Node.js 内置实现fs.readFileSync
。很明显,两者getData
都是fs.readFileSync
同步功能。有一天,您被告知将底层数据源切换到只能异步访问的存储库,例如 MongoDB。您还被告知要避免激怒您的用户,getData
不能将 API 更改为仅返回一个承诺或要求一个回调参数。你如何满足这两个要求?
使用回调/承诺的异步函数是 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 的解决方案,因此尽管不在 JSFiddle 中工作,您仍可以自由地要求任何 npm 包。