Недостатки read.sys

Следующий fragment кода создает текстовый файл, а затем читает его, перезаписывает и читает его снова. За исключением создания файла три операции ввода-вывода выполняются с использованием Node.js async readFile и writeFile.

Я не понимаю, почему первое чтение не возвращает ошибки, но никаких данных . Результат этого кода:

  • Начиная с …
  • Готово.
  • сначала прочитал возвращенный EMPTY данные!
  • написать закончено OK
  • второе чтение возвращенных данных: обновленный текст

Даже если операции должны происходить в произвольном порядке (из-за их асинхронного характера), я бы НЕ ожидал получить объект «пустой информации».

Любые идеи, почему я получаю пустые данные при чтении файла (и без ошибок)?

Есть ли что-нибудь, что я могу сделать, чтобы убедиться, что содержимое файла прочитано?

var fs = require('fs'); var fileName = __dirname + '/test.txt'; // Create the test file (this is sync on purpose) fs.writeFileSync(fileName, 'initial test text', 'utf8'); console.log("Starting..."); // Read async fs.readFile(fileName, 'utf8', function(err, data) { var msg = ""; if(err) console.log("first read returned error: ", err); else { if (data === null) console.log("first read returned NULL data!"); else if (data === "") console.log("first read returned EMPTY data!"); else console.log("first read returned data: ", data); } }); // Write async fs.writeFile(fileName, 'updated text', 'utf8', function(err) { var msg = ""; if(err) console.log("write finished with error: ", err); else console.log("write finished OK"); }); // Read async fs.readFile(fileName, 'utf8', function(err, data) { var msg = ""; if(err) console.log("second read returned error: ", err); else if (data === null) console.log("second read returned NULL data!"); else if (data === "") console.log("second read returned EMPTY data!"); else console.log("second read returned data: ", data); }); console.log("Done."); 

Ваш код запрашивает условия гонки. Ваша первая запись с синхронизацией, вероятно, записывает файл, но затем ваше первое чтение, второе чтение и второе чтение помещаются в цикл событий одновременно .

Что могло бы произойти здесь? Первое чтение получает разрешение на чтение из файловой системы, вторая запись получает разрешение на запись из файловой системы и сразу же обнуляет файл для будущего обновления, затем первое чтение читает пустой файл. Затем вторая запись начинает записывать данные, а второе чтение не получает разрешения на чтение, пока оно не будет выполнено.

Если вы хотите этого избежать, вам необходимо использовать stream:

 fs.writeFileSync(filename, 'initial', 'utf8'); fs.readFile(filename, 'utf8', function(err, data) { console.log(data); fs.writeFile(filename, 'text', 'utf8', function(err) { fs.readFile(filename, 'utf8', function(err, data) { console.log(data); }); }); }); 

Если эта «пирамида» оскорбляет вашу чувствительность к программированию (почему бы и нет?) Использовать функцию series асинхронных библиотек :

 fs.writeFileSync(filename, 'initial', 'utf8'); async.series([ function(callback) { fs.readFile(filename, 'utf8', callback); }, function(callback) { fs.writeFile(filename, 'text', 'utf8', callback); }, function(callback) { fs.readFile(filename, 'utf8', callback); } ], function(err, results) { if(err) console.log(err); console.log(results); // Should be: ['initial', null, 'text'] }); 

EDIT: более компактный, но также более «волшебный» для людей, не знакомых с async библиотекой и современными функциями Javascript:

 fs.writeFileSync(filename, 'initial', 'utf8'); async.series([ fs.readFile.bind(this, filename, 'utf8'), fs.writeFile.bind(this, filename, 'text', 'utf8'), fs.readFile.bind(this, filename, 'utf8'), ], function(err, results) { if(err) console.log(err); console.log(results); // Should be: ['initial', null, 'text'] }); 

EDIT2: Позволяет мне редактировать это редактирование без поиска определения bind . Первым параметром должен быть this объект (или то, что вы хотите использовать как this ).