# Асинхронная работа с 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'); } });`

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

← →
↑