Блокирующие и неблокирующие вызовы¶
Блокирующими считаются те операции, при выполнении которых процесс Node.js вынужден ждать ее окончания, прежде чем начать выполнять следующий код. Это происходит из-за того, что приостанавливается работа event loop.
Большинство синхронных методов в Node.js относятся к блокирующим, и чаще всего они выполняют операции ввода/вывода или работают с сетью. Практически все синхронные методы имеют в своем названии Sync
.
const fs = require('fs')
console.log(fs.readFileSync('./file.txt'))
console.log('After reading file')
Здесь с началом чтения файла file.txt
процесс блокируется и продолжает работу только с завершением операции чтения. Результат работы приведенного кода.
{содержимое файла}
After reading file
Чтобы избежать блокировки event loop и тем самым создавать высокопроизводительные Node.js приложения, используйте асинхронные методы. Почти наверняка каждому синхронному блокирующему методу соответствует метод с точно таким же функционалом, но асинхронный.
const fs = require('fs')
fs.readFile('./file.txt', (err, data) => {
if (err) throw err
console.log(data)
})
console.log('Before reading file')
В этом примере процесс не будет дожидаться окончания чтения файла, а продолжит выполнять следующий код. А когда содержимое файла будет получено - вызовет переданную методу readFile()
callback-функцию. Результат работы кода примера.
Before reading file
{содержимое файла}
Синхронные методы блокируют процесс выполнения, асинхронные - нет.
Самая распространенная ошибка при использовании асинхронных методов - полагать, что следующий за методом код будет выполнен после его завершения.
const fs = require('fs')
let fileContent
fs.readFile('./file.txt', (err, data) => {
if (err) throw err
fileContent = data
})
console.log(fileContent)
Здесь в консоль будет выведено undefined
, поскольку в момент вывода значения переменной fileContent
операция чтения еще не будет завершена. Чтобы избежать этого, необходимо занести код вывода содержимого файла в callback-функцию метода readFile()
или создать Promise
.
fs.readFile('./file.txt', (err, data) => {
if (err) throw err
fileContent = data
console.log(fileContent)
})