6

我尝试读取文件参数。当我制作这段代码时:

  var fs = require('fs'),
    size = new Object();
fs.stat(file, function(err,stats){
         if(!err){
            size=stats;
         }
      })
   console.log(size);

没关系,当我尝试使用功能时:

 var fs = require('fs'),
    size = new Object();
function writeinfile(file){
   fs.stat(file, function(err,stats){
         if(!err){
            size=stats;
         }
      })
   console.log(size.size);  
}
writeinfile('error.log');

这行不通。你能帮我变种 2 工作吗?

4

4 回答 4

12

您的 console.log 在您的 fs.stat 回调之外。解决它:

 var fs = require('fs'),
    size = new Object();
function writeinfile(file){
   fs.stat(file, function(err,stats){
         if(!err){
            size=stats;
            console.log(size.size);  
         }
      })

}
writeinfile('error.log');

我还重写了您的代码以在 Node.js 中使用更惯用(更常见)的语法:

var fs = require('fs');

function writeinfile (file, cb) {
  fs.stat(file, function(err,stats){
    if(err) return cb(err);
    cb(null, stats.size); 
  })
}

writeinfile('error.log', function(err, size) {
  if(err) {
    console.log(err);
    return;
  }
  console.log('The size of the file is ' + size);
});

正如 Herman 在他的回答中提到的,如果您不写入文件,最好选择一个更好的函数名称。

最后一件事,在 Javascript 中,您可以将{}其用作new Object(). 例如:var size = {};

于 2012-10-29T19:46:14.943 回答
1

你需要把 console.log(size.size); 在回调函数内部,但我认为我需要更好地解释。

您需要了解异步调用和 Node.js 事件循环。创建 Node.js 是为了以更好的方式并行化资源,即为 IO 密集型(如 Web 服务器)而不是 CPU 密集型的问题创建线程。这个想法是单线程的逻辑与非阻塞调用使用 IO 比创建多个线程并调用块函数来使用 IO 更好。

如果您使用另一种语言进行编程,您应该熟悉算法的同步版本:

var fs = require('fs'),
size = new Object();
function writeinfile(file) {
    var stats = fs.statSync(path);
    size = stats.size;
    console.log(size);
};

writeinfile('error.log');

这是 Node.js 代码,但这不是 Node 方式。当您调用 statSync() 时,您的脚本会阻塞以等待从磁盘读取统计信息。

但是,当您使用 just 时fs.stat(),您的程序将运行到代码结束,同时磁盘正在读取。所有下一行将在程序实现事件循环之前运行。就在 stat 准备好并且程序运行到结束时,事件循环将调用您在 call 中通过参数传递的回调函数fs.stat(callback)

因此,在您的代码中,您调用 stat(异步版本),并尝试使用尚未准备好的值,因为异步调用之后的代码总是会在回调被调用之前运行。

我认为第一个版本可以工作,因为您应该在解释器中手动输入代码,因此,您需要输入下一行的时间足以让程序实现事件循环。在这种模式下,每次你输入一个命令,回车,代码就会运行,也就是说,你得到一个返回,事件循环中的事件会在之后被调用。

于 2015-02-27T19:14:34.103 回答
1

在您的示例中,由于 fs.stat() 的异步特性,期望在 console.log(size) 运行时设置 size 的值是不正确的。

以下是实际发生的情况,按顺序:

  1. 您需要该fs模块并实例化一个新size对象。
  2. 你用回调调用 fs.stat(path,cb)
  3. 你打电话给 console.log(size)
  4. 然后,在未来的某个时候, fs.stat() 调用您的回调

事情之所以按此顺序发生,是因为由于文件 io 的异步特性,无法事先预测进行所需文件系统调用所需的时间。根据光盘当前正在执行的操作,可能需要 4 到 4000 毫秒或更多时间。

这就是我们依赖回调的原因,因为它们保证在应用它们的函数完成时发生,或者在这种情况下,当文件路径的状态已经确定时。

请不要难过。这是每个人在异步编程时都会犯的一个错误,也是编程节点时最难理解的概念。

于 2012-10-29T19:51:59.300 回答
0

您的代码有几个观察结果。但我们在这里学习:

  1. 确保将console.log回调放在内部(即在下面size=stats),这样您就可以在函数完成任务后获得所需的信息。

  2. 在上面添加这一行if (!err)

    如果(错误)console.log(错误);

您将看到以下内容

{ [Error: ENOENT, stat 'error.log'] errno: 34, code: 'ENOENT', path: 'error.log' }

这意味着路径上的错误。简单修复:使用fs.exists()检查文件是否存在,和/或始终确保在文件名前加上__dirname.

  1. 最后一行讨论writeinfile,但fs.stats为您提供有关文件的信息...我建议fs.write()用于此任务的更好功能。
于 2012-10-29T19:43:43.920 回答