asynchronousnodejs模块导出
我想知道什么是configuration模块导出的最佳方法。 在下面的例子中,“async.function”可能是一个FS或HTTP请求,为了举例而简化:
以下是示例代码(asynmodule.js):
var foo = "bar" async.function(function(response) { foo = "foobar"; // module.exports = foo; // having the export here breaks the app: foo is always undefined. }); // having the export here results in working code, but without the variable being set. module.exports = foo;
只有在执行了asynchronouscallback后,如何才能导出模块?
编辑一个关于我的实际用例的快速logging:我正在编写一个模块来在fs.exists()callback中configurationnconf( https://github.com/flatiron/nconf )(即它将parsing一个configuration文件,设置nconf)。
你的出口不能工作,因为它是在foo
声明里面的时候在函数之外。 但是如果你把输出放在里面,当你使用你的模块时,你不能确定输出是被定义的。
使用ansync系统的最佳方式是使用callback。 您需要导出callback分配方法来获取callback,并在asynchronous执行时调用它。
例:
var foo, callback; async.function(function(response) { foo = "foobar"; if( typeof callback == 'function' ){ callback(foo); } }); module.exports = function(cb){ if(typeof foo != 'undefined'){ cb(foo); // If foo is already define, I don't wait. } else { callback = cb; } }
这里的async.function
只是一个占位符来象征一个asynchronous调用。
主要
var fooMod = require('./foo.js'); fooMod(function(foo){ //Here code using foo; });
多种callback方式
如果您的模块需要被多次调用,您需要pipe理一个callback数组:
var foo, callbackList = []; async.function(function(response) { foo = "foobar"; // You can use all other form of array walk. for(var i = 0; i < callbackList.length; i++){ callbackList[i](foo) } }); module.exports = function(cb){ if(typeof foo != 'undefined'){ cb(foo); // If foo is already define, I don't wait. } else { callback.push(cb); } }
这里的async.function
只是一个占位符来象征一个asynchronous调用。
主要
var fooMod = require('./foo.js'); fooMod(function(foo){ //Here code using foo; });
承诺的方式
你也可以用Promise来解决这个问题。 该方法通过Promise的devise支持多个呼叫:
var foo, callback; module.exports = new Promise(function(resolve, reject){ async.function(function(response) { foo = "foobar" resolve(foo); }); });
这里的async.function
只是一个占位符来象征一个asynchronous调用。
主要
var fooMod = require('./foo.js').then(function(foo){ //Here code using foo; });
请参阅Promise文档
另一种方法是将variables包裹在一个对象中。
var Wrapper = function(){ this.foo = "bar"; this.init(); }; Wrapper.prototype.init = function(){ var wrapper = this; async.function(function(response) { wrapper.foo = "foobar"; }); } module.exports = new Wrapper();
如果初始化器有错误,至less你仍然得到未初始化的值,而不是挂起callback。
你也可以使用Promises:
一些-asynchronousmodule.js
module.exports = new Promise((resolve, reject) => { setTimeout(resolve.bind(null, 'someValueToBeReturned'), 2000); });
main.js
var asyncModule = require('./some-async-module'); asyncModule.then(promisedResult => console.log(promisedResult)); // outputs 'someValueToBeReturned' after 2 seconds
在不同的模块中可能会发生同样的情况,并且也会像预期的那样解决
在几家,其他-module.js
var asyncModule = require('./some-async-module'); asyncModule.then(promisedResult => console.log(promisedResult)); // also outputs 'someValueToBeReturned' after 2 seconds
请注意,promise对象被创build一次,然后被节点caching。 每个require('./some-async-module')
将返回相同的对象实例(在这种情况下是promise实例)。
ES6答案使用承诺:
const asyncFunc = () => { return new Promise((resolve, reject) => { // Where someAsyncFunction takes a callback, ie api call someAsyncFunction(data => { resolve(data) }) }) } export default asyncFunc ... import asyncFunc from './asyncFunc' asyncFunc().then(data => { console.log(data) })
或者你可以直接返回承诺本身:
const p = new Promise(...) export default p ... import p from './asyncModule' p.then(...)
一个ES7的方法是在module.exports中立即调用asynchronous函数 :
module.exports=(async function(){ //some async initiallizers //eg await the db module that has the same structure like this var db=await require("./db"); var foo="bar"; //resolve the export promise return { foo }; })()
稍后可能需要这样做:
(async function(){ var foo= await require("./theuppercode"); console.log(foo); })();
其他答案似乎是部分答案,并没有为我工作。 这似乎有点完整:
一些-module.js
var Wrapper = function(){ this.callbacks = []; this.foo = null; this.init(); }; Wrapper.prototype.init = function(){ var wrapper = this; async.function(function(response) { wrapper.foo = "foobar"; this.callbacks.forEach(function(callback){ callback(null, wrapper.foo); }); }); } Wrapper.prototype.get = function(cb) { if(typeof cb !== 'function') { return this.connection; // this could be null so probably just throw } if(this.foo) { return cb(null, this.foo); } this.callbacks.push(cb); } module.exports = new Wrapper();
main.js
var wrapper = require('./some-module'); wrapper.get(function(foo){ // foo will always be defined });
main2.js
var wrapper = require('./some-module'); wrapper.get(function(foo){ // foo will always be defined in another script });
- 为什么不应该默认所有的function是asynchronous的?
- 是否可以设置async:false为$ .getJSON调用
- ASP.NET MVC中的asynchronous操作是否使用.NET 4上的ThreadPool的线程
- 用于处理列表的C#asynchronous选项
- PHP中的asynchronousshell exec
- asynchronousJavaScript执行如何发生? 什么时候不用return语句?
- entity frameworkSaveChanges()与SaveChangesAsync()和Find()与FindAsync()
- 如何Async Files.ReadAllLines并等待结果?
- 如何在Java中asynchronous调用一个方法