Асинхронное программирование на JavaScript
Понятие асинхронности
Асинхронный (async) — это противоположное понятие синхронного (sync).
В традиционном однопоточном программировании, которое мы изучаем, выполнение программы синхронно (синхронность не означает, что все шаги выполняются одновременно; скорее, шаги выполняются последовательно в порядке потока управления). Однако понятие асинхронности не гарантирует синхронизацию, то есть выполнение асинхронного процесса больше не имеет последовательной связи с исходной последовательностью.
Проще говоря: синхронное выполнение следует порядку вашего кода, асинхронное выполнение не следует порядку кода, и асинхронное выполнение более эффективно.
Выше было объяснение концепции асинхронности. Далее объясним асинхронность простыми словами: асинхронность означает порождение дочернего потока из главного потока для выполнения задачи.

Когда использовать асинхронное программирование
Во фронтенд-программировании (а иногда и в бэкенде), при обработке коротких быстрых операций, например вычисления результата 1 + 1, их часто можно выполнить в главном потоке. Как поток, главный поток не может принимать несколько запросов одновременно. Поэтому, когда событие ещё не завершено, интерфейс не может обрабатывать другие запросы.
Теперь рассмотрим кнопку. Если мы зададим её событию onclick бесконечный цикл, то при нажатии кнопки вся веб-страница перестанет отвечать.
Чтобы избежать этой ситуации, мы часто используем дочерние потоки для обработки задач, которые могут занять достаточно много времени, чтобы пользователь это заметил, например чтения большого файла или выполнения сетевого запроса. Поскольку дочерний поток независим от главного потока, даже если возникает блокировка, это не повлияет на работу главного потока. Однако у дочерних потоков есть ограничение: после запуска они теряют синхронизацию с главным потоком, и мы не можем определить, когда они завершатся. Если после их завершения нужно что-то сделать, например обработать информацию от сервера, мы не можем вернуть её обратно в главный поток.
Чтобы решить эту проблему, функции асинхронных операций в JavaScript часто используют функции обратного вызова для обработки результатов асинхронных задач.
Функции обратного вызова
Функция обратного вызова — это функция, которой мы при запуске асинхронной задачи говорим: что делать после того, как ты завершишь эту задачу. Таким образом, главному потоку почти не нужно заботиться о состоянии асинхронной задачи; она сама справится от начала до конца.
Примеры
Попробуйте »
setTimeout в этой программе — это процесс, который занимает много времени (3 секунды). Его первый параметр — функция обратного вызова, а второй параметр — количество миллисекунд. После выполнения этой функции создаётся дочерний поток. Дочерний поток ждёт 3 секунды, затем выполняет функцию обратного вызова "print", которая выводит "EXAMPLE!" в командную строку.
Конечно, синтаксис JavaScript очень дружелюбен. Нам не нужно определять отдельную функцию print; мы часто записываем вышеприведённую программу так:
Примеры
Попробуйте »
Примечание:Поскольку setTimeout ждёт 3 секунды в дочернем потоке, главный поток не останавливается после выполнения функции setTimeout, поэтому:
Примеры
Попробуйте »
Результат выполнения этой программы:
EXAMPLE-1! // 三秒后子线程执行 EXAMPLE-2! // 主线程先执行
Асинхронный AJAX
Помимо функции setTimeout, асинхронные обратные вызовы широко используются в программировании AJAX. Подробнее об AJAX см.:https://www.example.com/ajax/ajax-tutorial.html
XMLHttpRequest часто используется для запроса XML- или JSON-данных с удаленного сервера. Стандартный объект XMLHttpRequest часто содержит несколько callback-функций:
Примеры
Попробуйте »
Свойства onload и onerror объекта XMLHttpRequest являются функциями, вызываемыми при успешном выполнении запроса и при ошибке соответственно. Если вы используете полную библиотеку jQuery, вы можете более элегантно использовать асинхронный AJAX:
Примеры
Попробуйте »