Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 异步nodejs模块导出_Node.js_Asynchronous - Fatal编程技术网

Node.js 异步nodejs模块导出

Node.js 异步nodejs模块导出,node.js,asynchronous,Node.js,Asynchronous,我想知道配置模块导出的最佳方法是什么。下面示例中的“async.function”可以是FS或HTTP请求,为便于示例而简化: 下面是示例代码(asynmodule.js): 如何仅在执行异步回调后导出模块 编辑 关于我的实际用例的简要说明:我正在编写一个模块,以便在fs.exists()回调中配置nconf()(即,它将解析一个配置文件并设置nconf) 导出无法工作,因为它在函数外部,而foo声明在内部。但是,如果将导出放在内部,则在使用模块时,无法确定是否定义了导出 使用ansync系统的

我想知道配置模块导出的最佳方法是什么。下面示例中的“async.function”可以是FS或HTTP请求,为便于示例而简化:

下面是示例代码(asynmodule.js):

如何仅在执行异步回调后导出模块

编辑
关于我的实际用例的简要说明:我正在编写一个模块,以便在fs.exists()回调中配置nconf()(即,它将解析一个配置文件并设置nconf)

导出无法工作,因为它在函数外部,而
foo
声明在内部。但是,如果将导出放在内部,则在使用模块时,无法确定是否定义了导出

使用ansync系统的最佳方法是使用回调。您需要导出回调分配方法来获取回调,并在异步执行时调用它

例如:

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
只是一个占位符,用来表示异步调用

大体上

var fooMod = require('./foo.js');
fooMod(function(foo){
    //Here code using foo;
});
var fooMod = require('./foo.js');
fooMod(function(foo){
    //Here code using foo;
});
var fooMod = require('./foo.js').then(function(foo){
    //Here code using foo;
});
多重回调方式 如果需要多次调用模块,则需要管理回调数组:

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);
    }
}
承诺方式 你也可以用承诺来解决这个问题。此方法通过Promise的设计支持多个调用:

var foo, callback;
module.exports = new Promise(function(resolve, reject){
    async.function(function(response) {
        foo = "foobar"

        resolve(foo);
    });
});
这里的
async.function
只是一个占位符,用来表示异步调用

大体上

var fooMod = require('./foo.js');
fooMod(function(foo){
    //Here code using foo;
});
var fooMod = require('./foo.js');
fooMod(function(foo){
    //Here code using foo;
});
var fooMod = require('./foo.js').then(function(foo){
    //Here code using foo;
});

请参见

另一种方法是将变量包装在对象中

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();

如果初始值设定项有错误,至少您仍然会得到未初始化的值,而不是挂起回调。

您还可以使用承诺:

一些异步模块.js

module.exports = new Promise((resolve, reject) => {
    setTimeout(resolve.bind(null, 'someValueToBeReturned'), 2000);
});
var asyncModule = require('./some-async-module');

asyncModule.then(promisedResult => console.log(promisedResult)); 
// outputs 'someValueToBeReturned' after 2 seconds
var asyncModule = require('./some-async-module');

asyncModule.then(promisedResult => console.log(promisedResult)); 
// also outputs 'someValueToBeReturned' after 2 seconds
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();
var wrapper = require('./some-module');

wrapper.get(function(foo){
    // foo will always be defined
});
var wrapper = require('./some-module');

wrapper.get(function(foo){
    // foo will always be defined in another script
});
main.js

module.exports = new Promise((resolve, reject) => {
    setTimeout(resolve.bind(null, 'someValueToBeReturned'), 2000);
});
var asyncModule = require('./some-async-module');

asyncModule.then(promisedResult => console.log(promisedResult)); 
// outputs 'someValueToBeReturned' after 2 seconds
var asyncModule = require('./some-async-module');

asyncModule.then(promisedResult => console.log(promisedResult)); 
// also outputs 'someValueToBeReturned' after 2 seconds
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();
var wrapper = require('./some-module');

wrapper.get(function(foo){
    // foo will always be defined
});
var wrapper = require('./some-module');

wrapper.get(function(foo){
    // foo will always be defined in another script
});

同样的情况也可能发生在不同的模块中,并将按预期解决:

在其他一些模块中。js

module.exports = new Promise((resolve, reject) => {
    setTimeout(resolve.bind(null, 'someValueToBeReturned'), 2000);
});
var asyncModule = require('./some-async-module');

asyncModule.then(promisedResult => console.log(promisedResult)); 
// outputs 'someValueToBeReturned' after 2 seconds
var asyncModule = require('./some-async-module');

asyncModule.then(promisedResult => console.log(promisedResult)); 
// also outputs 'someValueToBeReturned' after 2 seconds
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();
var wrapper = require('./some-module');

wrapper.get(function(foo){
    // foo will always be defined
});
var wrapper = require('./some-module');

wrapper.get(function(foo){
    // foo will always be defined in another script
});


请注意,promise对象创建一次,然后由节点缓存。每个
require('./some async module')
将返回相同的对象实例(本例中为promise实例)。

其他答案似乎是部分答案,对我来说不起作用。这似乎有点完整:

一些模块.js

module.exports = new Promise((resolve, reject) => {
    setTimeout(resolve.bind(null, 'someValueToBeReturned'), 2000);
});
var asyncModule = require('./some-async-module');

asyncModule.then(promisedResult => console.log(promisedResult)); 
// outputs 'someValueToBeReturned' after 2 seconds
var asyncModule = require('./some-async-module');

asyncModule.then(promisedResult => console.log(promisedResult)); 
// also outputs 'someValueToBeReturned' after 2 seconds
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();
var wrapper = require('./some-module');

wrapper.get(function(foo){
    // foo will always be defined
});
var wrapper = require('./some-module');

wrapper.get(function(foo){
    // foo will always be defined in another script
});
main.js

module.exports = new Promise((resolve, reject) => {
    setTimeout(resolve.bind(null, 'someValueToBeReturned'), 2000);
});
var asyncModule = require('./some-async-module');

asyncModule.then(promisedResult => console.log(promisedResult)); 
// outputs 'someValueToBeReturned' after 2 seconds
var asyncModule = require('./some-async-module');

asyncModule.then(promisedResult => console.log(promisedResult)); 
// also outputs 'someValueToBeReturned' after 2 seconds
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();
var wrapper = require('./some-module');

wrapper.get(function(foo){
    // foo will always be defined
});
var wrapper = require('./some-module');

wrapper.get(function(foo){
    // foo will always be defined in another script
});
main2.js

module.exports = new Promise((resolve, reject) => {
    setTimeout(resolve.bind(null, 'someValueToBeReturned'), 2000);
});
var asyncModule = require('./some-async-module');

asyncModule.then(promisedResult => console.log(promisedResult)); 
// outputs 'someValueToBeReturned' after 2 seconds
var asyncModule = require('./some-async-module');

asyncModule.then(promisedResult => console.log(promisedResult)); 
// also outputs 'someValueToBeReturned' after 2 seconds
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();
var wrapper = require('./some-module');

wrapper.get(function(foo){
    // foo will always be defined
});
var wrapper = require('./some-module');

wrapper.get(function(foo){
    // foo will always be defined in another script
});

ES6使用承诺回答:

const asyncFunc = () => {
    return new Promise((resolve, reject) => {
        // Where someAsyncFunction takes a callback, i.e. 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中立即调用的异步函数:

module.exports = (async function(){
 //some async initiallizers
 //e.g. 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);
})();

我一直在玩弄我的实际用例,如果使用不存在的文件调用nconf.file(),那么nconf加载很好,所以现在我不需要解决方案。但是我仍然对这种方法感兴趣。我有同样的问题,我想导出一个承诺,并且
要求
异步加载依赖项。我认为这是可能的巴贝尔格式化程序。然而,我认为这不是一个好的解决方案(如果两个独立的(主)系统不工作)文件在没有foo准备好的情况下调用此函数,对吗?只有一个回调会被触发,以最新调用的为准。在这种情况下,是的。因为我们不管理回调堆栈。但是使用一个数组来存储所有回调很容易解决这个问题。详细信息:ReferenceError:未定义异步我有两个问题:(1)在您的第一个示例中,else块的本质是什么?在这个示例中,您说
if(typeof foo!=“undefined”){cb(foo);//如果foo已经定义,我就不等待了。}else{callback=cb;}
(2)这个块是否意味着
需要
s继续调用这个模块,直到它生成一个值(来自异步过程)?或者它是否假设在模块的整个生命周期内,只有一次回调给模块,即后续调用可以忽略
cb
参数?@IWantAnswers,在这个例子中,不同的模块可能需要多次回调,需要使用
foo
值。但您不知道何时发生。因此,何时开始回调,何时开始回调e
foo
值不存在,但您存储回调以等待异步调用的返回。在异步过程结束时,所有存储的回调都取消堆栈,并且不再使用数组。此时,如果另一个模块需要此模块并订阅以获取
foo
值,则该值已设置,因此您可以绕过当您需要模块时,如何获取“foo”?var wrapper=require('wrapper');console.log(wrapper.foo)这是ES6和Promission的正确、现代的答案。谢谢。问题:您直接返回函数而不是
Promise
有什么原因吗?如果您直接返回
Promise
,您可以使用
asyncFunc访问它。然后(…)
,对吗?非常新,所以我想听听你的意见。那也行。我想当我写这个例子的时候,我是在导出一个异步方法的类,它的形式就像一个函数。但是你可以像这样导出承诺:
const p=new Promise(…);导出默认p;
然后在您的导入模块中从“…”;p.then(…);
太棒了,感谢您的澄清。我想这是个人喜好,或者有最佳实践方法使用其中一种吗?我想这取决于您是否需要将参数传递给异步模块,这通常对我来说都是如此(例如,
id
或其他参数)。在第一个示例中,如果
const asyncFunc=(id)=>…
则可以在函数中使用
id
。您可以像调用
asyncFunc(id)一样调用它。然后(…)
。但是如果不需要传递任何参数,直接返回承诺也可以。为什么要使用
回调(null,wrapper.foo);
而不是
回调(wrapper.foo);
?@IWantAnswers第一个参数是error,第二个参数是result你能解释调用它和不调用它之间的区别/含义吗?如果你不调用函数,你在不执行的情况下导出函数