【问题标题】:module.exports issue in nodeJSnodeJS中的module.exports问题
【发布时间】:2015-12-18 09:36:22
【问题描述】:

我正在练习 node.js,我有一些疑问。

我有一个 csv 文件 (users.csv),并且我创建了一个节点模块 (library.js) 来返回 csv 文件中的值。当我从我的程序中调用模块时,我得到了奇怪的结果。我的程序如下。

users.csv

id,name
1,Jim
2,Jo

库.js

var csv             = require("fast-csv");
var DataToBeReturned = [];
exports.users = function () {
        csv.fromPath("users.csv", {headers: true})
        .on("data",function(data){
            DataToBeReturned.push(data);
        })
        .on("end",function(){   
            console.log(DataToBeReturned.length);
            return DataToBeReturned;
        });
};

app.js

var mylibrary = require('./library.js');
console.log(mylibrary.users());
console.log(mylibrary.users());

我的预期输出是

2
[{ id: '1', name: 'Jim' },{ id: '2', name: 'Jo' }]
2
[{ id: '1', name: 'Jim' },{ id: '2', name: 'Jo' }]

相反,我得到了

undefined
undefined
3
4

我的疑惑:

  1. 为什么返回值未定义?
  2. 为什么我的计数不总是 2?

提前致谢。

【问题讨论】:

标签: javascript node.js csv module


【解决方案1】:

我自己无法测试您的代码,但通过阅读您的代码,您遇到了两个问题,这与您的问题密切相关。

首先,您遇到了大多数人在开始使用 nodejs 时遇到的典型问题。您正在同步调用异步函数。这就是为什么它在前两次打印 undefined 的原因,您正在打印调用用户的结果。由于用户还没有完成运行,它的值是不确定的。您应该使用回调实现library.js 函数用户。例如:

exports.users = function (callback) {
    csv.fromPath("users.csv", {headers: true})
    .on("data",function(data){
        DataToBeReturned.push(data);
    })
    .on("end",function(){   
        console.log(DataToBeReturned.length);
        return callback(null, DataToBeReturned);
    });
};

然后在app.js 中,您将实现它以使用回调。

var csv             = require("fast-csv");
// err is just a nodejs convention, if you add error checking to users,
// instead of throwing an error, you would pass it back as the first agrument
// to the callback
mylibrary.users(function(err, users) {
    console.log(users);
});
mylibrary.users(function(err, users) {
    console.log(users);
});

其次,您指的是来自 users 函数的全局变量。那就是你打印出 3 和 4。这两个调用同时作用于变量。当第一次调用完成并返回值时,第二次调用也已经修改了数组。所以,你想移动数组声明而不是你的函数,所以只有那里的代码可以访问它。

exports.users = function () {
    var DataToBeReturned = [];
    // the rest of your code.
};

编辑:模块内的代码被缓存,所以它只执行一次。然后,每个引用它的脚本都会简单地返回该副本。如果您只需要读取 csv 一次,请充分利用这一点。

var DataToBeReturned = [];
var called = false;
function read(callback) {
    if (called) {
        process.nextTick(function() {
            return callback(null, DataToBeReturned);
        });
        return;
    } else {
        called = true;
        csv.fromPath("users.csv", {headers: true})
        .on("data",function(data){
            DataToBeReturned.push(data);
        })
        .on("end",function(){   
            console.log(DataToBeReturned.length);
            return callback(null, DataToBeReturned);
        });
    }
};

exports.users = function(callback) {
    return read(callback);
};

process.nextTick 部分很重要,有关其工作原理的更多信息可以在文档中找到here。

【讨论】:

  • 谢谢@Zequ。有了这个解决方案,我得到了正确的答案。但我又面临另一个问题。每次我调用该方法时,它都在读取文件。相反,我只需要读取一次文件
猜你喜欢
  • 1970-01-01
  • 2019-01-02
  • 1970-01-01
  • 2023-03-06
  • 2017-05-21
  • 2020-08-31
  • 2015-10-03
  • 1970-01-01
  • 2021-08-01
相关资源
最近更新 更多