所以,我有以下js文件:
test_api.js:
var request = require("request")
//I actually have a url here.API call which returns JSON.
var url = "";
request({
url: url,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
module.exports = body;
console.log(body) // Prints the json response
}
});
测试.js:
var api = require('./test_api.js');
console.log(api);
所以,当我运行 node test.js 时,我得到:
console.log(body) // Prints the json response
console.log(api); //Prints an empty object
知道为什么我会得到一个空对象吗?
最佳答案
当您调用request()
时,您向其传递一个回调函数。该回调函数在将来的某个时候被调用(这是一个异步回调)。同时,模块的其余部分继续执行,并且模块初始化完成,但尚未向 module.exports 分配任何内容。
因此,当调用者这样做时:
var api = require('./test_api.js');
模块已完成加载,并且没有为 module.exports
分配任何内容,因此,它仍然是一个空对象,因此 api
仅包含一个空对象。
然后,一段时间后,您的 request()
操作完成并调用其回调。然后您将一些内容分配给 module.exports
,但为时已晚。该模块已经加载,并且调用者在您替换旧的 module.exports
之前已经获取了它。
node.js 中的所有网络 I/O 都是异步的。这意味着完成回调将在未来某个不确定的时间被调用,并且 Javascript 的其余部分将继续执行。唯一可以处理异步结果的地方是在完成回调内部或从该回调调用的其他函数中。或者,您可以使用 Promise 来为您完成此类工作。
<小时/>因此,基本上您无法返回通过加载模块的异步操作检索到的结果,也无法将它们分配给 module.exports
。因此,现代的设计方法是导出一个 Promise 或一个返回 Promise 的函数,然后调用者可以在 Promise 上使用 .then()
来访问结果。
这是一种现代方法来实现您尝试使用 Promise 执行的操作。
var request = require("request")
//I actually have a url here.API call which returns JSON.
var url = "";
function requestP(options) {
return new Promise((resolve, reject) => {
request(options, (error, response, body) => {
if (error) {
reject(error);
} else if (response.statusCode !== 200) {
reject(new Error(`Network request returned status code ${response.statusCode}`));
} else {
resolve(body);
}
});
});
}
module.exports = requestP({url, json: true});
然后,调用者将像这样使用它:
let api = require('./test_api.js');
api.then(body => {
// process body here
}).catch(err => {
// process err here
});
有关返回异步结果的更一般性讨论,请参阅 How do I return the response from an asynchronous call?
关于javascript - module.exports 返回一个空对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42731381/