为对象赋值时,未定义的位置来自何处?

时间:2014-03-07 15:39:59

标签: javascript node.js

下面的代码打开一个文件并读取打印到控制台的内容。我把它修改为我认为会返回一个字符串,但我得到了未定义。目标不是打印内容,而是将它们保存在我可以在代码中的任何位置使用的变量中。

(我正在学习Node和JavaScript。这个问题可能之前已经被问过了;我只是不知道要把它放在哪个上下文中,这真的有助于我开发对JavaScript的理解。)

var fs = require('fs');

function sql_file(sql_file, cb) {
    var fileName = "./SQLs/" + sql_file;
    fs.readFile(fileName, function(err, buffer) {
        if (err) return cb(err);
        return cb(null, buffer.toString());
    });
}


var t = sql_file('inventory.sql', function(err, contents) {
    return contents.toString();
});


console.log(t);

以下是我迷路的地方:如果t代表sql_file的回复,那么你怎么得到undefined

1 个答案:

答案 0 :(得分:1)

正如人们在评论中指出的那样,代码的问题在于您缺少异步执行的概念。如果在代码中添加一些console.log()语句,以查看每个步骤的执行时间,您将能够发现问题:

var fs = require('fs');

function sql_file(sql_file, cb) {
    console.log('about to read file');
    var fileName = "./SQLs/" + sql_file;
    fs.readFile(fileName, function(err, buffer) {
        console.log('the file has been read');
        if (err) return cb(err);
        return cb(null, buffer.toString());
    });
    console.log('call to read file made (but not finished)');
    // the call to sql_file ends here and returns nothing/undefined
}


var t = sql_file('inventory.sql', function(err, contents) {
    // contents will have the value when this call back is executed
    // in your case this is once the file has been read. 
    // Keep in mind that sql_file will ALWAYS return null, though.
    return contents.toString();
});

console.log(t);

如果使用这些console.log()运行代码,您将看到为什么总是未定义。一旦您的代码使用异步调用(如fs.readFile),您就不能依赖于代码的线性执行。

您应该按照以下方式编写代码,以便按预期打印值:

var fs = require('fs');

function sql_file(sql_file, cb) {
    console.log('about to read file');
    var fileName = "./SQLs/" + sql_file;
    fs.readFile(fileName, function(err, buffer) {
        console.log('the file has been read');
        if (err) return cb(err);
        return cb(null, buffer.toString());
    });
    console.log('call to read file made (but not finished)');
}


// sql_file will always return NULL but the value will 
// be available to you once the callback is executed.    
sql_file('inventory.sql', function(err, contents) {

    console.log(contents.toString());
});

这里带走的是,一旦你已经异步,你就会全身心投入。当其中一个调用(在你的情况下为fs.readFile)是异步时,你不能指望下一行中的值可用。