Это очень общий вопрос, но я не совсем понимаю. Когда я предпочел бы один над другим? Кажется, я не понимаю, какие ситуации могут возникнуть, что явно должно было бы обойти друг друга. Есть ли веские причины, чтобы избежать x/use x?
Когда я предпочел бы один над другим?
Используйте версии 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
но есть и другие.
Когда я предпочел бы один над другим?
На сервере, предназначенном для масштабирования и обслуживания потребностей многих пользователей, вы должны использовать только синхронный ввод-вывод во время инициализации сервера. Фактически, require()
сам использует синхронный ввод-вывод. Во всех других частях вашего сервера, которые обрабатывают входящие запросы после того, как сервер уже запущен и работает, вы будете использовать только асинхронный ввод-вывод.
Существуют и другие варианты использования node.js, помимо создания сервера. Например, предположим, что вы хотите создать скрипт, который будет разбирать гигантский файл и искать определенные слова или фразы. И этот сценарий предназначен для самостоятельной обработки одного файла и не имеет постоянных функций сервера, и у него нет особых причин для ввода-вывода из нескольких источников одновременно. В этом случае отлично использовать синхронный ввод-вывод. Например, я создал сценарий node.js, который помогает мне создавать файлы резервных копий (удаление файлов резервных копий, соответствующих определенным возрастным критериям), и мой компьютер автоматически запускает этот сценарий один раз в день. Не было никаких оснований использовать асинхронный ввод-вывод для этого типа использования, поэтому я использовал синхронный ввод-вывод и сделал код более простым для записи.
Кажется, я не понимаю, какие ситуации могут возникнуть, что явно должно было бы обойти друг друга. Есть ли веские причины, чтобы избежать x/use x?
Избегайте использования синхронного ввода-вывода в обработчиках запросов сервера. Из-за однопоточного характера Javascript в node.js использование синхронных операций ввода-вывода блокирует поток javascript node.js, поэтому он может делать только одну вещь за раз (что является смертью для многопользовательского сервера), тогда как асинхронный ввод /O не блокирует thread.js поток Javascript (позволяющий потенциально удовлетворять потребности многих пользователей).
В ситуациях, не связанных с несколькими пользователями (код, который делает только одно дело для одного пользователя), синхронный ввод-вывод может быть предпочтительным, поскольку писать код проще и нет преимуществ при использовании асинхронного ввода-вывода.
Я думал о электронном приложении с nodejs, которое просто читает файл и не понимает, какая разница будет действительно, если моему программному обеспечению просто нужно дождаться, когда этот файл будет загружаться в любом случае.
Если это однопользовательское приложение, и вам нечего делать в ожидании чтения файла в памяти (никаких сокетов для ответа на них, обновлений на экране, никаких других запросов для работы, никакого другого файла операции, которые будут выполняться параллельно), тогда нет преимущества для использования асинхронного ввода-вывода, поэтому синхронный ввод-вывод будет просто прекрасным и, вероятно, немного проще для кода.