Nodejs async & sync чтение и запись файлов - когда использовать что?

1

Это очень общий вопрос, но я не совсем понимаю. Когда я предпочел бы один над другим? Кажется, я не понимаю, какие ситуации могут возникнуть, что явно должно было бы обойти друг друга. Есть ли веские причины, чтобы избежать x/use x?

  • 0
    Не менее общий ответ: любая операция синхронизации блокирует любую другую операцию. Менее общий пример: если у вас есть веб-сервер и вы читаете файл синхронно, запросы не будут обрабатываться, пока этот файл не будет прочитан. Итак: избегайте блокировок, за исключением одноразовых вещей при запуске, и избегайте блокировок при вводе / выводе, тем более что это занимает много времени, а иногда и непредсказуемое время.
  • 0
    Большое спасибо, это делает это намного понятнее, например, на примере веб-сервера и входящих запросов. Я подумал о приложении для работы с электроникой с nodejs, которое просто читает файл и не понимает, что это на самом деле изменит, если мое программное обеспечение действительно просто должно ждать загрузки этого файла в любом случае. Спасибо.
Показать ещё 1 комментарий
Теги:
asynchronous

2 ответа

2

Когда я предпочел бы один над другим?

Используйте версии non- Sync (асинхронные), если только в буквальном смысле ничего не нужно, чтобы ваша программа выполнялась во время ожидания ввода-вывода, и в этом случае Sync файлы прекрасны; подробнее см. ниже...

Есть ли веские причины, чтобы избежать x/use x?

Да. NodeJS запускает ваш JavaScript-код в одном потоке. Если вы используете версию Sync функции ввода-вывода, этот поток блокируется в ожидании ввода-вывода и больше ничего не может сделать. Если вы используете асинхронную версию, I/O может продолжать работать в фоновом режиме, когда поток JavaScript работает с другой работой; завершение ввода-вывода будет поставлено в очередь как задание для потока JavaScript, чтобы вернуться к нему позже.

Если вы используете приложение для переднего плана, которому не нужно ничего делать, пока ожидающий ввода-вывода не работает, вы, вероятно, прекрасно используете вызовы Sync. Но если вы используете Node для обработки нескольких вещей сразу (например, веб-запросов), лучше всего использовать асинхронные версии.

В комментарии вы добавили по вопросу, который вы сказали:

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

Я практически не знаю Electron, но я отмечаю, что он использует "основной" процесс для управления окнами, а затем процесс "рендеринга" для каждого окна (ссылки). В этом случае использование функций Sync будет блокировать соответствующий процесс, что может повлиять на реакцию приложения или окна. Но у меня нет никаких глубоких знаний об электронном (более жалко).


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

// (Obviously this is just an example, you wouldn't actually read and write a file this way, you'd use streaming...)
fs.readFile("file1.txt", function(err, data) {
    if (err) {
        // Do something about the error...
    } else {
        fs.writeFile("file2.txt", data, function(err) {
            if (err) {
                // Do something about the error...
            } else {
                // All good
        });
    }
});

Затем появились обещания, и если вы использовали обещанную версию операции (показанную здесь с псевдонимами, такими как fs.promisifiedXYZ), она по-прежнему включала обратные вызовы, но они были более сложными:

// (See earlier caveat, just an example)
fs.promisifiedReadFile("file1.txt")
.then(function(data) {
    return fs.promisifiedWriteFile("file2.txt", data);
})
.then(function() {
    // All good
})
.catch(function(err) {
    // Do something about the error...
});

Теперь, в последних версиях Node, вы можете использовать ES2017+ async/await синтаксис для записи синхронного вида кода, который, по сути, асинхронный:

// (See earlier caveat, just an example)
(async () => {
    try {
        const data = await fs.promisifiedReadFile("file1.txt");
        fs.promisifiedWriteFile("file2.txt", data);
        // All good
    } catch (err) {
        // Do something about the error...
    }
})();

Node API предшествует обещаниям и имеет свои собственные соглашения. Существуют различные библиотеки, которые помогут вам "пролонгировать" API обратного вызова в стиле Node, чтобы вместо этого использовать обещания. Одно promisify но есть и другие.

2

Когда я предпочел бы один над другим?

На сервере, предназначенном для масштабирования и обслуживания потребностей многих пользователей, вы должны использовать только синхронный ввод-вывод во время инициализации сервера. Фактически, require() сам использует синхронный ввод-вывод. Во всех других частях вашего сервера, которые обрабатывают входящие запросы после того, как сервер уже запущен и работает, вы будете использовать только асинхронный ввод-вывод.

Существуют и другие варианты использования node.js, помимо создания сервера. Например, предположим, что вы хотите создать скрипт, который будет разбирать гигантский файл и искать определенные слова или фразы. И этот сценарий предназначен для самостоятельной обработки одного файла и не имеет постоянных функций сервера, и у него нет особых причин для ввода-вывода из нескольких источников одновременно. В этом случае отлично использовать синхронный ввод-вывод. Например, я создал сценарий node.js, который помогает мне создавать файлы резервных копий (удаление файлов резервных копий, соответствующих определенным возрастным критериям), и мой компьютер автоматически запускает этот сценарий один раз в день. Не было никаких оснований использовать асинхронный ввод-вывод для этого типа использования, поэтому я использовал синхронный ввод-вывод и сделал код более простым для записи.

Кажется, я не понимаю, какие ситуации могут возникнуть, что явно должно было бы обойти друг друга. Есть ли веские причины, чтобы избежать x/use x?

Избегайте использования синхронного ввода-вывода в обработчиках запросов сервера. Из-за однопоточного характера Javascript в node.js использование синхронных операций ввода-вывода блокирует поток javascript node.js, поэтому он может делать только одну вещь за раз (что является смертью для многопользовательского сервера), тогда как асинхронный ввод /O не блокирует thread.js поток Javascript (позволяющий потенциально удовлетворять потребности многих пользователей).

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню