Как вы, возможно, знаете, среда исполнения языка JavaScript является «единственным потоком».
Так называемый «единственный поток» означает, что одна задача может быть выполнена только за раз. Если есть несколько задач, вы должны встать в очередь, выполнить предыдущую задачу, выполнить следующую задачу и так далее.
Преимущество этой модели заключается в том, что ее относительно просто внедрить, а среда выполнения относительно проста; Недостаток заключается в том, что до тех пор, пока есть задача, которая занимает много времени, последующие задачи должны быть в очереди, что задержит выполнение всей программы. Общие браузеры не отвечают (фальшивая смерть) часто потому, что определенная часть кода JavaScript работает в течение длительного времени (например, мертвая петля), что приводит к застенчивому в этом месте всю страницу, и другие задачи не могут быть выполнены.
Чтобы решить эту проблему, язык JavaScript делит режим выполнения задач на два типа: синхронные (синхронные) и асинхронные (асинхронные).
«Синхронный режим» - это шаблон предыдущего раздела. Последняя задача ожидает завершения предыдущей задачи, а затем выполняется. Порядок выполнения программы является последовательным и синхронным с порядком расположения задач; «Асинхронный режим» совершенно другой. Каждая задача имеет одну или несколько функций обратного вызова (обратные вызовы). После того, как предыдущая задача закончилась, это не следующая задача, но функция обратного вызова выполняется. Последняя задача выполняется без ожидания, пока предыдущая задача завершится, поэтому порядок выполнения программы непоследовательна и асинхронно с порядком соглашения задач.
«Асинхронный режим» очень важен. Со стороны браузера долгосрочные операции должны быть выполнены асинхронно, чтобы избежать браузера не терять ответа. Лучшим примером являются операции Ajax. На стороне сервера «асинхронный режим» является даже единственным режимом, поскольку среда выполнения однопоточена, если все HTTP-запросы будут выполнены синхронно, производительность сервера резко упадет и скоро потеряет свой ответ.
В этой статье суммируются 4 метода программирования «асинхронного режима». Понимание их позволяет вам писать программы JavaScript с более разумной структурой, лучшей производительностью и более удобным обслуживанием.
1. Функция обратного вызова
Это самый основной метод асинхронного программирования.
Предположим, что есть две функции F1 и F2, последние ожидают результата выполнения первого.
Кода -копия выглядит следующим образом:
f1 ();
f2 ();
Если F1 является трудоемкой задачей, вы можете рассмотреть возможность переписывания F1 и написания F2 в качестве функции обратного вызова F1.
Кода -копия выглядит следующим образом:
Функция F1 (обратный вызов) {
settimeout (function () {
// код задачи F1
перезвонить();
}, 1000);
}
Код выполнения становится таким:
Кода -копия выглядит следующим образом:
F1 (F2);
Таким образом, мы превращаем синхронные операции в асинхронные операции. F1 не будет блокировать операцию программы, которая в первую очередь эквивалентно выполнению основной логики программы и откладыванию выполнения трудоемкой операции.
Преимущество функций обратного вызова заключается в том, что они просты, легко понять и развернуть, и недостаток в том, что они не способствуют чтению и обслуживанию кода. Они сильно связаны (соединение) между различными частями, и процесс будет очень хаотичным, и каждая задача может указать только одну функцию обратного вызова.
2. Мониторинг событий
Другая идея-принять модель, управляемую событиями. Выполнение задачи зависит не от порядка кода, а от того, происходит ли событие.
Давайте возьмем F1 и F2 в качестве примеров. Во -первых, свяжите событие для F1 (метод написания jQuery, используемый здесь).
Кода -копия выглядит следующим образом:
f1.on ('Dode', F2);
Вышеуказанная строка кода означает, что когда выполняется событие в F1, F2 выполняется. Затем перепишите F1:
Кода -копия выглядит следующим образом:
функция f1 () {
settimeout (function () {
// код задачи F1
f1.trigger ('dode');
}, 1000);
}
f1.trigger ('dode') означает, что после завершения выполнения событие выполнено сразу же запускается, тем самым начинает выполнять F2.
Преимущество этого метода заключается в том, что его относительно легко понять. Он может привязать несколько событий, и каждое событие может указывать несколько функций обратного вызова, и оно может быть «развязкой», что способствует модуляризации. Недостатком является то, что вся программа станет ориентированной на события, и процесс работы станет очень неясным.
3. Публикуйте/подпишитесь
«Событие» в предыдущем разделе может быть полностью понято как «сигнал».
Мы предполагаем, что есть «сигнальный центр». После выполнения задачи сигнал публикуется в центре сигнала. Другие задачи могут «подписаться» сигнал в центр сигнала, чтобы знать, когда он может начать выполнение. Это называется «шаблон публикации-подписки», также известный как «шаблон наблюдателя».
Есть много реализаций этой модели. Ниже приведено крошечный паб/подставка Бена Альмана, который является плагином для jQuery.
Во -первых, F2 подписывается на сигнал «выполнен» на «Сигнальный центр» jQuery.
Кода -копия выглядит следующим образом:
jquery.subscribe ("Dode", F2);
Затем F1 переписан следующим образом:
Кода -копия выглядит следующим образом:
функция f1 () {
settimeout (function () {
// код задачи F1
jquery.publish ("Dode");
}, 1000);
}
jquery.publish («dode») означает, что после завершения F1 выполнение «сделано» сигнал выпускается в jQuery «Сигнал», тем самым вызывая выполнение F2.
Кроме того, после выполнения F2 отписать также отписаться от подписки.
Кода -копия выглядит следующим образом:
jquery.unsubscribe ("Dode", F2);
Природа этого метода похож на «прослушивание событий», но значительно лучше, чем последний. Потому что мы можем отслеживать работу программы, просмотрев «Центр сообщений», чтобы понять, сколько сигналов существует и сколько подписчиков для каждого сигнала.
4. обещает объект
Объект обещаний - это спецификация, предложенная рабочей группой CommonJS, с целью предоставления единого интерфейса для асинхронного программирования.
Проще говоря, его идея состоит в том, что каждая асинхронная задача возвращает объект обещания, который имеет метод, который позволяет указать функцию обратного вызова. Например, функция обратного вызова F2 F1 может быть написана как:
Кода -копия выглядит следующим образом:
f1 (). Тогда (F2);
F1 должен быть переписан следующим образом (здесь используется реализация jQuery):
Кода -копия выглядит следующим образом:
функция f1 () {
var dfd = $ .deferred ();
settimeout (function () {
// код задачи F1
dfd.resolve ();
}, 500);
возврат dfd.promise;
}
Преимущество написания таким образом состоит в том, что функция обратного вызова стала методом записи цепочки, и программный поток можно увидеть очень четко, и существует полный набор методов поддержки, которые могут реализовать много мощных функций.
Например, укажите несколько функций обратного вызова:
Кода -копия выглядит следующим образом:
f1 (). Тогда (F2) .Then (F3);
Например, укажите функцию обратного вызова, когда возникает ошибка:
Кода -копия выглядит следующим образом:
f1 (). Тогда (f2) .fail (f3);
Более того, у него есть преимущество, что ни один из предыдущих трех методов не имеет: если задача была выполнена, добавьте функцию обратного вызова, и функция обратного вызова будет выполнена немедленно. Таким образом, вам не нужно беспокоиться о том, чтобы пропустить событие или сигнал. Недостатком этого метода является то, что относительно сложно написать и понять.