module.exports返回一个空对象

时间:2017-03-11 04:33:41

标签: javascript node.js

所以,我有以下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

    }
});

test.js:

var api = require('./test_api.js');
console.log(api);

所以,当我运行节点test.js时,我得到:

console.log(body) // Prints the json response
console.log(api); //Prints an empty object

我知道为什么我会得到一个空物体?

3 个答案:

答案 0 :(得分:2)

当你致电request()时,你会传递一个回调函数。该回调函数在将来某个时候被调用(这是一个异步回调)。同时,模块的其余部分继续执行,模块初始化完成,但尚未分配给module.exports

所以,当来电者这样做时:

var api = require('./test_api.js');

模块已完成加载,但没有为module.exports分配任何内容,因此它仍然是一个空对象,因此api只包含一个空对象。

然后,稍后,您的request()操作完成并调用其回调。然后你给module.exports分配一些东西,但为时已晚。模块已经加载,调用者在更换之前已经抓住了旧module.exports

node.js中的所有网络I / O都是异步的。这意味着将来将完成回调调用一些不确定的时间,并继续执行其余的Javascript。您可以处理异步结果的唯一位置是在完成回调内或从该回调调用的其他一些函数中。或者,你可以使用promises为你做这类工作。

因此,基本上您无法返回通过加载模块而使用异步操作检索的结果,并且您无法将它们分配给module.exports。相反,设计它的现代方法是导出一个promise或一个返回promise的函数,然后调用者可以在promise上使用.then()来访问结果。

这将是一种现代化的方式来实现您尝试使用承诺执行的操作。

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?

答案 1 :(得分:1)

您不能异步分配module.exports或分配给exports。相反,您应该考虑导出一个接受回调并执行请求的函数(如果需要,缓存/重用结果)。

答案 2 :(得分:0)

test_api.js:

var request = require("request")

//I actually have a url here.API call which returns JSON.
var url = "";

module.exports = function (callback) {

    request({
        url: url,
        json: true
    }, function (error, response, body) {
        if (error) {
            callback(error, null);
        }
        if (!error && response.statusCode === 200) {
            console.log(body) // Prints the json response
            callback(null, body);
        }
    });
};

test.js:

var api = require('./test_api.js');
function callback(error, body) {
    if (error) {
        console.log(error);
    } else {
        console.log(body);
    }
}
api(callback);