等待NodeJS中的asynchronous方法

我看起来高低,只能find如何编写asynchronous函数,我已经明白了。

我试图做的是在触发的事件[EventEmitter]中运行asynchronous方法,但是这样一个简单的事情似乎只是根本不可能,因为我可以find。

考虑以下…

// Your basic async method.. function doSomething(callback) { var obj = { title: 'hello' }; // Fire an event for event handlers to alter the object. // EvenEmitters are called synchronously eventobj.emit('alter_object', obj); callback(null, obj); } // when this event is fired, I want to manipulate the data eventobj.on('alter_object', function(obj) { obj.title += " world!"; // Calling this async function here means that our // event handler will return before our data is retrieved. somemodule.asyncFunction(callback(err, data) { obj.data = data; }); }); 

正如您在最后几行看到的,事件处理程序将在添加对象的data属性之前完成。

我需要的是可以将asynchronous函数转换为同步函数并在那里获得结果的东西。 所以例如…

 obj.data = somemodule.asyncFunction(); 

我看了wait.for模块, async模块,这些都不会工作。 我甚至研究过yield方法,但是它似乎还没有完全实现到V8引擎中。

我也试过使用while循环等待数据填充,但这只是带来了CPU超载的问题。

有没有人经历过这个,并find了一个devise模式来解决这个问题?

您不能在node.js中将asynchronous函数转换为同步函数。 这是不能做到的。

如果你有一个asynchronous的结果,你不能同步返回或等待它。 您将不得不重新devise接口以使用asynchronous接口(几乎总是需要传入一个将在结果准备就绪时调用的callback函数)。

如果你想在你的.emit()事件之后做一些事情,而事件本身要asynchronous执行某些事情,而你想等到asynchronous事件完成之后,事件发射器可能不是正确的接口。 你宁愿有一个函数调用返回一个承诺或作为一个参数callback。 你可以操纵一个事件发射器来使用它,但是当asynchronous操作完成时,你必须回发第二个事件,并让原来的调用者在接收到第二个事件之前不要做第二个事件(这实际上不是一个好办法走)。

底线 – 你需要一个与asynchronous响应(例如callback或承诺)不同的devise。

似乎我想做的事情是不可能的,两种模式相冲突。 为了达到我想要的目的,我将模块封装到一个类似数组的对象中,并使用一些事件方法将其传递给模块的对象,该对象inheritance了async-eventemitter类。

所以,想想这样…

  • 我的自定义应用程序模块可能会inheritanceasync-eventemitter模块,因此它们具有.on().emit()等方法。
  • 我创build了一个自定义的数组项,这将允许我将事件传递给将会asynchronous工作的模块。

我创build的代码(这不完全或完美)…

 // My private indexer for accessing the modules array (below) by name. var module_dict = {}; // An array of my modules on my (express) app object app.modules = []; // Here I extended the array with easier ways to add and find modules. // Haven't removed some code to trim down this. Let me know if you want the code. Object.defineProperty(app.modules, 'contains', { enumerable: false, ... }); Object.defineProperty(app.modules, 'find', { enumerable: false, ... }); // Allows us to add a hook/(async)event to a module, if it exists Object.defineProperty(app.modules, 'on', { enumerable: false, configurable: false, value: function(modulename, action, func) { if (app.modules.contains(modulename)) { var modu = app.modules.find(modulename); if (modu.module && modu.module['on']) { // This will pass on the event to the module's object that // will have the async-eventemitter inherited modu.module.on(action, func); } } } }); Object.defineProperty(app.modules, 'once', { enumerable: false, configurable: false, value: function(modulename, action, func) { if (app.modules.contains(modulename)) { var modu = app.modules.find(modulename); if (modu.on) { modu.on(action, func); } } } }); 

这允许我通过简单地调用类似下面的… .on(module_name, event_name, callback)来将事件处理程序绑定到模块。

 app.modules.on('my_special_module_name', 'loaded', function(err, data, next) { // ...async stuff, that then calls next to continue to the next event... if (data.filename.endsWith('.jpg')) data.dimensions = { width: 100, height: 100 }; next(err, data); }); 

然后执行它,我会做一些像(expression)…

 app.get('/foo', function(req, res, next) { var data = { filename: 'bar.jpg' }; // Now have event handlers alter/update our data // (eg, extend an object about a file with image data if that file is an image file). my_special_module.emit('loaded', data, function(err, data) { if (err) next(err); res.send(data); next(); }); }); 

再一次,这只是我所做的一个例子,所以我可能错过了上面我的副本中的某些东西,但实际上这是我最终使用的devise,它的工作方式就像一种享受,我能够扩展数据在一个对象之后被推出到我的HTTP响应,而不必取代主[expressjs]对象的标准EventEmitter模型。

(例如,我为图片文件添加了图片数据,如果有人想要这些代码,请告诉我,我非常乐意分享我所做的)