Я пытаюсь понять, что именно происходит с некоторыми функциями JavaScript, которые делают их асинхронными. У вас может быть такая функция:
function someRandomFunction () {
for (let i of everything) {
iterator++
something = true
hello = that + whatever
}
}
Ничто об этой функции не является асинхронным. Он делает много всего, но делает это очень быстро.
Но затем возьмите функцию Node.js следующим образом:
fs.readFile('path/to/file', (err, data) => {
// do something
})
Эта функция объявлена асинхронной. Но почему? В чем причина этого?
Это потому, что для чтения файла требуется определенное количество времени, поэтому оно асинхронно? Почему это асинхронно при переходе через некоторые переменные и выполнение некоторых вычислений не является асинхронным?
"Идея" чего-то асинхронного означает "мы отказались от контроля над другим операционным кодом, и мы понятия не имеем, когда этот другой код позволит нам снова работать".
Таким образом, в вашем нижнем примере вы даете контроль над операциями файловой системы узла для чтения файла. Мы не знаем, насколько велик этот файл, поэтому нет способа предвидеть, сколько времени потребуется для завершения. Поэтому JavaScript позволяет нам предоставлять "обратный вызов", который запускается, когда операция async завершена. Когда обратный вызов выполняется, управление возвращается в наш код.
Верхний пример является синхронным, потому что ваш код поддерживает контроль над операцией, а Javascript выполняет код синхронно по своей природе.
Это основной, но фундаментальный вопрос. Передача функции другой функции не делает код асинхронным автоматически. Все это касается работы с другим фрагментом кода, в основном неизвестного происхождения, возможно, но не обязательно связанным с механизмом IO операционной системы. Другими словами, вы просите, чтобы что-то случилось из области существующего в настоящее время контекста JS, передав задачу известным или неизвестным ресурсам, которые, возможно, работают в отдельном потоке.
Как я уже сказал, это может быть операция ввода-вывода или доступ к базе данных, о которой вы не знаете
За занавесками эти чуждые коды, наконец, запускают очередь событий, чтобы вызвать функцию обратного вызова через драйвер. На некоторых чистых функциональных языках, таких как Haskell, такие действия строго сохраняются в стороне от контекста и должны обрабатываться функциями монадического типа. В JS это в основном выполняется асинхронным рабочим процессом с помощью обратных вызовов, обещаний или асинхронного механизма.
Когда вы передадите задачу во внешний мир, тогда не будет никакого способа вмешаться в ваш синхронный код.
С точки зрения JavaScript разница между синхронными и асинхронными функциями заключается в том, где и когда выполняется код. Синхронные функции выполняются сразу один за другим в текущем стеке вызовов. Асинхронные функции передаются в цикл событий, а значения возвращаются после завершения выполнения текущего стека вызовов.
Предостережение: ничего в JavaScript по-настоящему асинхронно из-за того, что JS работает только на одном потоке процесса
Функция либо явно синхронна, либо асинхронна; нет "определенного количества времени", которое автоматически делает его асинхронным.
Важная вещь, которую следует помнить с помощью Node, заключается в том, что это "асинхронный ввод-вывод", что означает, что ничто не является асинхронным без какого-либо ввода/вывода в/из процесса. Обычно вы видите это с чтением/записью файлов, вызовами базы данных и всем, что требует сетевого вызова.