Асинхронная работа с fs через коллбэки в NodeJS

Давайте теперь рассмотрим асинхронную работу с файловой системой. Как правило, в NodeJS все методы модуля fs существуют в двух вариантах: в синхронном и асинхронном.

Например, для синхронного чтения файла используется метод readFileSync, а для асинхронного - readFile. Аналогично для записи файла существует пара writeFileSync и writeFile.

Асинхронное чтение файла

Метод readFile первым параметром принимает имя или путь к файлу, вторым параметром - кодировку, а третьим - коллбэк, который выполнится после чтения файла.

В коллбэк следует передавать два параметра. В первый параметр попадет объект с ошибкой, если она произойдет, а во второй - текст прочитанного файла.

Давайте для примера прочитаем текст какого-нибудь файла:

fs.readFile('readme.txt', 'utf8', function(err, data) { console.log(data); });

Дан файл с числом. Прочитайте этот файл и выведите в консоль квадрат этого числа.

Проверка асинхронности

Можно убедится в том, что чтение файла происходит асинхронно. Для этого выведем что-нибудь в консоль после работы с методом readFile:

fs.readFile('readme.txt', 'utf8', function(err, data) { console.log(data); }); console.log('!!!');

Как вы уже знаете, коллбэк выполнится, когда файл будет прочитан. А пока файл читается, код скрипта будет выполнятся дальше. Это значит, что в консоли сначала появится результат второго console.log, а потом первого.

Проверьте, что код после метода readFile будет выполнен раньше, чем будет прочитан файл.

Обработка исключительных ситуаций

Так как наш код асинхронный, то исключительные ситуации нельзя поймать через try-catch. Для обработки исключений в коллбэке предназначен первый параметр. Этот параметр будет содержать null, если исключения не случилось, или объект с ошибкой, если исключение произошло.

Давайте допишем код коллбэка так, чтобы он обрабатывал исключительные ситуации:

fs.readFile('readme.txt', 'utf8', function(err, data) { if (!err) { console.log(data); } else { console.log('ошибка', err); } });

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

Асинхронная запись файла

Асинхронная запись текста в файл выполняется аналогично:

fs.writeFile('readme.txt', 'text', function(err) { if (err) { console.log('ошибка'); } });

С помощью цикла создайте 10 файлов, содержащих целые числа от 1 до 10.

Асинхронное чтение нескольких файлов

Пусть у нас есть два файла с числами. Давайте найдем произведение этих чисел. Очевидно, что для этого нам нужно прочитать оба этих файла.

Но, так как код асинхронный, нам нужно читать второй файл в коллбэке первого:

fs.readFile('readme1.txt', 'utf8', function(err, data1) { if (!err) { fs.readFile('readme2.txt', 'utf8', function(err, data2) { if (!err) { console.log(data1 * data2); } else { console.log('ошибка чтения файла readme2'); } }); } else { console.log('ошибка чтения файла readme1'); } });

Даны три файла с числами. Выведите в консоль сумму этих чисел.

Даны пять файлов с числами. Выведите в консоль сумму этих чисел.

Асинхронное чтение и запись файла

Предположим нам нужно прочитать файл, сделать его текстом операцию и записать обратно в этот или другой файл. В этом случае запись в файл нужно будет делать в коллбэке чтения:

fs.readFile('readme.txt', 'utf8', function(err, data) { if (!err) { fs.writeFile('readme.txt', data + '!', function(err) { if (err) { console.log('ошибка записи файла'); } }); } else { console.log('ошибка чтения файла'); } });

Дан файл с числом. Запишите в этот файл квадрат этого числа.

Даны три файла с числами. Запишите в новый файл сумму этих чисел.

Стрелочные функции

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

Давайте переделаем предыдущий код на стрелочные функции:

fs.readFile('readme.txt', 'utf8', (err, data) => { if (!err) { fs.writeFile('readme.txt', data + '!', err => { if (err) { console.log('ошибка записи файла'); } }); } else { console.log('ошибка чтения файла'); } });

Дан код:

fs.readFile('readme1.txt', 'utf8', function(err, data1) { if (!err) { fs.readFile('readme2.txt', 'utf8', function(err, data2) { if (!err) { fs.writeFile('readme.txt', data1 + data2, function(err) { if (err) { console.log('ошибка записи файла'); } }); } else { console.log('ошибка чтения файла readme2'); } }); } else { console.log('ошибка чтения файла readme1'); } });

Перепишите его через стрелочные функции.