假设您维护了一个公开函数 getData
的库,您的用户调用它来获取实际数据:
var output = getData();
遮罩下的数据保存在一个文件中,因此您使用内置的 fs.readFileSync
中的 Node.js 实现了 getData
。很明显,getData
和 fs.readFileSync
都是同步函数。有一天,您被告知将底层数据源切换到只能异步访问的 repo,比如 MongoDB。您还被告知要避免激怒您的用户,getData
API 不能被更改为仅返回一个承诺或要求回调参数。你如何满足这两个要求?
使用回调/承诺的异步函数是 JavasScript 和 Node.js 的 DNA。任何非平凡的 JS 应用程序都可能充斥着这种编码风格。但是这种做法很容易导致所谓的回调金字塔的厄运。更糟糕的是,如果调用链中的任何调用方中的任何代码都依赖于异步函数的结果,那么这些代码也必须包装在回调函数中,从而对调用方施加编码样式约束。有时我发现需要将一个异步函数(通常由第三方库提供)封装成一个同步函数,以避免大规模的全局重构。在这个主题上搜索解决方案通常会得到从中派生的 节点光纤或 npm 包。但纤维不能解决我面临的问题。甚至费伯斯的作者提供的例子也说明了这一缺陷:
...
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)
如果 function Fiber 真的将异步函数睡眠转换为同步,那么输出应该是:
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 中工作。