JavaScript文件系统函数未按预期工作

2022-07-21 00:00:00 arrays node.js javascript fs

我有一段简单的代码可以将js列表写入js文件。

// Requiring fs module in which
// writeFile function is defined.
var fs = require('fs');

// first overwrite any pre-existing file with the start of the list
fs.writeFile('Output.js', 'export const addressPoints = [', function (err) {
  if (err) throw err;
  console.log('Create file Output.js');
});

for (let i = 0; i < 100; i++) {
    // var string_row = "[" + latlon_datum1_row[i] + "],";
    var string_row = "HI"
    console.log(string_row);
    fs.appendFile('Output.js', string_row, function (err) {
        if (err) throw err;
        console.log('Writing file contents line', i);
    });
}

fs.appendFile('Output.js', '];', function (err) {
if (err) throw err;
    console.log('Append file Output.js');
});

可以将其分为三个部分,一个初始组件创建新的js脚本,并向其中添加‘EXPORT Const AddressPoints=[’。之后,运行for循环来写入列表的项,最后将‘];’附加到文件的末尾。

非常奇怪的是,代码并没有按预期工作。预计控制台日志应如下所示

Create file Output.js
Writing file contents line 1
Writing file contents line 2
Writing file contents line 3
...
Writing file contents line 99
Append file Output.js

但是,输出被打乱并以错误的顺序写入(显示最后几行):

...
Writing file contents line 96
Writing file contents line 97
Writing file contents line 98
Append file Output.js
Writing file contents line 99
Writing file contents line 91
Writing file contents line 79
Writing file contents line 68

有没有方法可以更快地做到这一点?如果不是,为什么会出现此错误?我想这和文件系统的关闭有关,但我对js不是很熟悉。


解决方案

您的控制台日志详细信息。

如您所见,日志的顺序错误。这是由于NodeJS和Java脚本的异步性造成的。

您需要使用回调或承诺来等待上一操作的结果。

示例:读取文件并打印其内容

错误

fs.readFile('/tmp/foo.txt',function (err, data) {
});

console.log('data is...');

正确

fs.readFile('/tmp/foo.txt',function (err, data) {
  console.log('data is:'+data);
});

如您所见,ReadFile和几乎所有NodeJS函数都是异步的。这意味着我们不能像Java、C#或Python那样以顺序或同步模式思考。在这种情况下,读取文件时需要执行函数:

function (err, data) {
  console.log('data is:'+data);
}

回调

将在异步操作后执行的工作传递函数。

var fs = require('fs');

fs.writeFile('Output.js', 'export const addressPoints = [', function (err) {
  if (err) throw err;
  console.log('Create file Output.js');

  //execute after file was updated
  var newContent = "";
  for (let i = 0; i < 100; i++) {
    var string_row = "HI"
    console.log(string_row);
    newContent += string_row+"
";    
  }
  newContent += "];
";      
  
  fs.appendFile('Output.js', newContent, function (err) {
    if (err) throw err;
    console.log('Output.js was updated');
  });
  
});

或可读性更好一点

var fs = require('fs');

fs.writeFile('Output.js', 'export const addressPoints = [', createCustomFile);

function createCustomFile(err, data){
  //logic here
}

劣势

如果需要执行更多操作,将会是一场噩梦

承诺等待(&A)

与嵌套回调相比,编写更具可读性(继续异步)的代码的方法

var fs = require('fs');

async function main(){
  await fs.promises.writeFile('Output.js', 'export const addressPoints = [');
  console.log('Create file Output.js');

  for (let i = 0; i < 100; i++) {
      var string_row = "HI"
      console.log(string_row);
      await fs.promises.appendFile('Output.js', string_row);
      console.log('Writing file contents line', i);
  }
  
  await fs.promises.appendFile('Output.js', '];');
  console.log('Append file Output.js');
}

//launch
//don't forget to catch async exceptions here!
main().catch(e => { console.error(e); process.exit(1) })

相关文章