Я знаю, что функция обратного вызова работает асинхронно, но почему?
в какой части синтаксиса предоставляет информацию о том, что эта функция должна выполняться в другом потоке и неблокирующих?
рассмотрим простой асинхронный ввод-вывод в узле.js
var fs = require('fs');
var path = process.argv[2];
fs.readFile(path, 'utf8', function(err,data) {
var lines = data.split('n');
console.log(lines.length-1);
});
что именно делает трюк, что это происходит в фоновом режиме? Может ли кто-нибудь объяснить это точно или вставить ссылку на какой-то хороший ресурс? Везде, где я смотрел, есть много информации о том, что такое обратный вызов, но никто не объясняет, почему он действительно работает так.
Это не конкретный вопрос о node.js, речь идет об общей концепции обратного вызова на каждом языке программирования.
изменить:
вероятно, пример, который я привел, здесь не лучший. Поэтому давайте не будем рассматривать этот узел.фрагмент кода js. Я спрашиваю вообще - что делает трюк, который программа продолжает выполнять, когда функция обратного вызова encounter. Что такое синтаксис это делает концепцию обратного вызова неблокирующей?
спасибо заранее!
3 ответов
здесь ничего в синтаксисе, который говорит вам, что ваш обратный вызов выполняется асинхронно. Обратные вызовы могут быть асинхронными, например:
setTimeout(function(){
console.log("this is async");
}, 100);
или он может быть синхронным, например:
an_array.forEach(function(x){
console.log("this is sync");
});
Итак, как вы можете знать, будет ли функция вызывать обратный вызов синхронно или асинхронно? Единственный надежный способ-прочитать документацию.
вы также можете написать тест, чтобы узнать, если документация не доступно:
var t = "this is async";
some_function(function(){
t = "this is sync";
});
console.log(t);
как работает асинхронный код
Javascript, как таковой, не имеет функции для асинхронного выполнения функций. Если вы хотите написать асинхронную функцию, у вас есть два варианта:
используйте другую асинхронную функцию, такую как
setTimeout
или веб-работники для выполнения вашей логики.писать ее в с.
как для как C закодировал функции (как setTimeout
) реализовать асинхронное выполнение? Все это связано с циклом событий (или в основном).
Цикл Событий
внутри веб-браузера есть этот кусок кода, который используется для создания сетей. Первоначально сетевой код мог загружать только одну вещь: саму HTML-страницу. Когда Мосиак изобрел <img>
тег сетевой код эволюционировал для загрузки нескольких ресурсов. Затем реализованы в Netscape прогрессивный рендеринг картинки, они должны были сделайте сетевой код асинхронным, чтобы они могли рисовать страницу до загрузки всех изображений и обновлять каждое изображение постепенно и индивидуально. Это источник цикла событий.
в центре браузера есть цикл событий, который развился из асинхронного сетевого кода. Поэтому неудивительно, что в качестве ядра он использует примитив ввода-вывода:select()
(или что-то подобное, например, опрос, epoll и т. д. в зависимости от ОС).
на select()
функция в C позволяет ждать нескольких операций ввода-вывода в одном потоке без необходимости создания дополнительных потоков. select()
выглядит примерно так:
select (max, readlist, writelist, errlist, timeout)
чтобы он ждал ввода-вывода (из сокета или диска), вы бы добавили файловый дескриптор в readlist
и оно возвратит когда данные доступные на любом из ваших каналов и/О. После его возвращения вы можете продолжить обработку данных.
интерпретатор javascript сохраняет ваш обратный вызов, а затем вызывает и есть. Интерпретатор ведет список всех тайм-аутов и вычисляет, что ему нужно передать как timeout
для select()
. Тогда когда select()
возвращает в дополнение к выяснению, есть ли какие-либо обратные вызовы, которые должны быть вызваны из-за операции ввода-вывода интерпретатор также проверяет любые истекшие таймауты, которые должны быть вызваны.
так охватывает практически все функциональные возможности, необходимые для реализации асинхронных функций. Но современные браузеры также имеют веб-работников. В случае веб-работников браузер порождает потоки для асинхронного выполнения кода javascript. Для обратной связи в основной поток работники должны по-прежнему взаимодействовать с циклом событий (
обратный вызов не обязательно является асинхронным. Исполнение полностью зависит от того, как fs.readFile
решает обработать параметр функции.
в JavaScript вы можете выполнять функцию асинхронно, используя, например,setTimeout.
Обсуждение и ресурсы:
как узел.JS реализует неблокирующий ввод-вывод?
модель и событие параллелизма Петля
существует два типа обратных вызовов, различающихся тем, как они управляют потоком данных во время выполнения:блокирование вызовов (также известный как синхронные вызовы или вызовы) и отложенные вызовы (также известный как асинхронные вызовы).
прежде всего, если что-то не асинхронно, это означает, что оно блокируется. Таким образом, бегун javascript останавливается на этой строке, пока эта функция не закончится (это то, что сделал бы readFileSync).
Как мы все знаем, fs-это библиотека ввода-вывода, поэтому такие вещи требуют времени (скажите аппаратному обеспечению, чтобы прочитать некоторые файлы, это не что-то сделано сразу), поэтому имеет смысл, что все, что не требует только процессора, это асинхронно, потому что это занимает время, и не нужно замораживать остальную часть код для ожидания другой части оборудования (в то время как процессор простаивает).
Я надеюсь, это решит ваши сомнения.