В настоящее время в спросе участвует большое количество асинхронных операций, и фактические страницы все чаще склонны к приложениям для одностраничных. В будущем вы можете использовать магистраль, угловой, нокаут и другие рамки, но проблема асинхронного программирования - первая проблема, с которой сталкиваются. С ростом узлов асинхронное программирование стало очень горячей темой. После периода обучения и практики приведены некоторые детали асинхронного программирования.
1. Классификация асинхронного программирования
Методы решения асинхронной задачи обычно включают в себя: прямой обратный вызов, паб/субмоть (режим события), библиотека управления асинхронной библиотекой (например, асинхрон, когда), обещание, генератор и т. Д.
1.1 Функция обратного вызова
Функции обратного вызовов обычно используются для решения асинхронных решений, часто открытых и используемых, простых для понимания и очень простых в реализации в библиотеках или функциях. Это также метод, который люди часто используют при использовании асинхронного программирования.
Однако метод функции обратного вызова имеет следующие проблемы:
1. может быть сформирована вложенная пирамида зла, и код нелегко читать;
2. может быть соответствующая только одна функция обратного вызова, что становится пределом во многих сценариях.
1.2 Pub/Sub -режим (событие)
Этот шаблон также называется режимом события, который является событиями функций обратного вызова и очень распространена в библиотеках классов, таких как jQuery.
В режиме публикации абонента не возникает проблемы синхронных и асинхронных вызовов, но в узле, эмит -вызовы в основном инициируются асинхронно с циклом события. Этот режим часто используется для отделки бизнес -логики. Издателям событий не нужно обращать внимание на зарегистрированную функцию обратного вызова, и при этом им не нужно обращать внимание на количество функций обратного вызова. Данные могут передаваться гибко через сообщения.
Преимущества этой модели: 1. Легко понять; 2. больше не ограничивается одной функцией обратного вызова.
Когда дело доходит до плохих вещей: 1. Вам нужно использовать библиотеку классов; 2. Порядок событий и функций обратного вызова очень важен
Кода -копия выглядит следующим образом:
var img = document.queryselect (#id);
img.addeventlistener ('load', function () {
// изображение загружено
......
});
img.addeventlistener ('error', function () {
// что -то пошло не так
......
});
Есть две проблемы с приведенным выше кодом:
а IMG фактически была загружена, и в настоящее время функция обратного вызова загрузки. В результате обратный вызов не будет выполнен, но он все еще надеется выполнить соответствующую функцию обратного вызова.
Кода -копия выглядит следующим образом:
var img = document.queryselect (#id);
function Load () {
...
}
if (img.complete) {
нагрузка();
} еще {
img.addeventListener ('Load', Load);
}
img.addeventlistener ('error', function () {
// что -то пошло не так
......
});
беременный Невозможно хорошо справиться с исключениями
Вывод: механизм событий лучше всего подходит для работы с повторными событиями на одном и том же объекте, и нет необходимости рассматривать событие до того, как функция обратного вызова будет связана.
1.3 Асинхронная библиотека управления
Текущие асинхронные библиотеки в основном включают Q, When.js, Win.js, RSVP.JS и т. Д.
Характеристикой этих библиотек является то, что код является линейным и может быть записан сверху вниз, в соответствии с естественными привычками.
Плохие вещи также различаются в стилях, которые неудобны для чтения и увеличения затрат на обучение.
1.4 Обещание
Обещание переводится на китайский как обещание. Лично после завершения асинхронно это даст внешний результат (успех или неудачу) и пообещал, что результат больше не изменится. Другими словами, обещание отражает окончательное значение результата возврата операции (обещание представляет возможное значение, возвращаемое после единого завершения операции). В настоящее время обещание было введено в спецификацию ES6, а усовершенствованные браузеры, такие как Chrome и Firefox, реализовали этот собственный метод внутри, который довольно удобен в использовании.
Ниже приведены характеристики обещания из следующих аспектов:
1.4.1 Статус
Он содержит три состояния: ожидающие, выполненные и отвергнутые. Три состояния могут пройти только два перехода (от ожидания ---> исполненного, ожидающего-> отклоненного), и переход состояния может происходить только один раз.
1.4.2 Тогда метод
Затем метод затем используется для указания функции обратного вызова после завершения асинхронного события.
Этот метод можно сказать, что является методом обещания души, который дает обещание полным магии. Есть несколько конкретных проявлений следующим образом:
а) Затем метод возвращает обещание. Это обеспечивает последовательные операции множественных асинхронных операций.
Что касается желтого круга 1 на приведенном выше рисунке, обработка значения является более сложной частью обещания. Обработка стоимости разделена на две ситуации: объект обещания и непространственный объект.
Когда значение не является типом обещания, просто используйте значение в качестве значения параметра разрешения второго обещания; Когда это тип обещания, статус и параметры обещания2 полностью определяются значением. Можно считать, что PromSie2 - это марионетка стоимости, а Orders2 - это просто мост, соединяющий различные асинхронные.
Кода -копия выглядит следующим образом:
Sport.Prototype.Then = function (Onfulfiled, Onrejected) {
вернуть новое обещание (функция (Resolve, dize) {// Обещание здесь помечено как Special2
ручка({
Onfulfiled: Onfulfiled,
Onrehected: Onrejected,
Решить: разрешить,
отвергнуть: отклонить
})
});
}
Ручке функции (отложено) {
var harderfn;
if (state === 'Fulfilled') {
handlefn = deferred.onfulfilled;
} else if (state === 'отклонил') {
handlefn = deferred.onrejected;
}
var ret = handlefn (значение);
отсрочен. Resolve (RET); // Обратите внимание, что решимость в это время является решимостью обещания2
}
функция Resolve (val) {
if (val && typeof val.then === 'function') {
Val.Then (Resolve); // Если Val является объектом обещания или объектом Class Promise, состояние обещания2 полностью определяется VAL
возвращаться;
}
if (обратный вызов) {// обратный вызов - это указанная функция обратного вызова
обратный вызов (val);
}
}
Б) Реализуется преобразование между несколькими различными асинхронными библиотеками.
Существует объект, который тогда называется асинхронным, который относится к объекту с тогдашним методом. Пока объект объекта имеет метод тогдашнего, он может быть преобразован, например:
Кода -копия выглядит следующим образом:
var deferred = $ ('aa.ajax'); // !! deferred.then === true
var p = promise.resolve (deferred);
P.Then (......)
1.4.3 Спецификация Commonjs/A Speciation
В настоящее время существуют Speak/A и Speak/A+ для спецификаций, касающихся обещания, что показывает, что реализация обещания довольно сложная.
Кода -копия выглядит следующим образом:
Затем (Fulfilledhandler, DecuceedHandler, ProgressHandler)
1.4.4 Примечания
Функция обратного вызова в обещании делится значением. При обработке результатов значение передается как параметр для соответствующей функции обратного вызова. Если значение является объектом, будьте осторожны, чтобы не легко изменить значение.
Кода -копия выглядит следующим образом:
var p = resport.resolve ({x: 1});
P.Then (function (val) {
console.log ('первый обратный вызов:'+val.x ++);
});
P.Then (function (val) {
console.log ('второй обратный вызов:' + val.x)
})
// первый обратный вызов: 1
// Второй обратный вызов: 2
1.5 Генератор
Все вышеперечисленные методы основаны на функции обратного вызова для завершения асинхронных операций, и они являются не чем иным, как инкапсулированием функции обратного вызова. ES6 предлагает генератор, который добавляет способы решения асинхронных операций и больше не выполняется на основе функций обратного вызова.
Самая большая особенность генератора заключается в том, что он может пауза и перезапуск функций, что очень способствует решению асинхронных операций. Объединение паузы генератора с обработкой исключений обещания может решить проблему асинхронного программирования более элегантно. Ссылка на конкретную реализацию: Кайл Симпсон
2. Проблемы с асинхронным программированием
2.1 Обработка исключений
а) Асинхронные события включают две ссылки: выдача асинхронных запросов и результаты обработки. Эти две ссылки связаны через петли событий. Затем, когда попробуйте поймать, чтобы выполнить захват исключений, вам нужно его захватить.
Кода -копия выглядит следующим образом:
пытаться {
Asyncevent (обратный вызов);
} catch (err) {
......
}
Приведенный выше код не может поймать исключение в обратном вызове и может получить исключение только в процессе запроса. У этого есть проблемы: если выпуск запроса и обработка запроса завершены двумя людьми, то есть проблемы при обработке исключений?
б) обещание реализует доставку исключений, что приносит некоторые преимущества, чтобы гарантировать, что код не заблокирован в реальных проектах. Однако, если есть много асинхронных событий, нелегко выяснить, какое асинхронное событие создает исключение.
Кода -копия выглядит следующим образом:
// Описание сцены: Информация о тревоге по цене цены в CRM, включая конкурентную информацию. Тем не менее, для получения конкурентной информации требуется много времени. Чтобы избежать медленного запроса, бэкэнд разбивает запись на две части, чтобы получить ее отдельно.
// Шаг 1: Получить информацию о тревоге, в дополнение к информации о конкуренции
function getPriceAlarmData () {
вернуть новое обещание (функция (Resolve) {
Y.io (url, {
Метод: 'Get',
данные: params,
on: function () {
Успех: function (id, data) {
Resolve (AlarmData);
}
}
});
});
}
// После получения информации о тревоге перейдите, чтобы получить информацию о конкуренции
getPriceAlarmData (). Затем (function (data) {
// рендеринг данных, в дополнение к конкурентной информации
рендеринг (данные);
вернуть новое обещание (функция (Resolve) {
Y.io (url, {
Метод: 'Get',
ДАННЫЕ: {armedlist: data},
on: function () {
Успех: function (id, compdata) {
Resolve (Compdata);
}
}
});
});
}) // после получения всех данных, рендеринга информации о конкуренции
.then (function (data) {
// рендеринг информации о торгах
рендеринг (данные)
}, function (err) {
// Обработка исключений
console.log (err);
});
Приведенный выше код может быть преобразован в следующее:
Кода -копия выглядит следующим образом:
пытаться{
// Получить информацию о тревоге, кроме конкуренции
var AlarmData = AlarmDataExctemptCompare ();
рендеринг (armeddata);
// запрос информации о конкуренции на основе информации о тревоге
var Conveliverata = getCompareInfo (AlarmData);
рендеринг (по сравнению);
} catch (err) {
console.log (err.message);
}
В приведенном выше примере исключение обрабатывается в конце, так что, когда исключение происходит в определенной ссылке, мы не можем точно знать, какое событие генерируется.
2.2 jQuery.Deferred Проблема
Асинхронные операции также реализованы в jQuery, но они не соответствуют спецификациям обещания/A+ в реализации и в основном отражаются в следующих аспектах:
а Количество параметров: стандартное обещание может принять только один параметр, в то время как jQuery может передавать несколько параметров
Кода -копия выглядит следующим образом:
функция asyncinjquery () {
var d = new $ .deferred ();
settimeout (function () {
D.resolve (1, 2);
}, 100);
возврат d.promise ()
}
asyncinjquery (). Затем (function (val1, val2) {
console.log ('output:', val1, val2);
});
// Вывод: 1 2
беременный Обработка исключений в обработке результатов
Кода -копия выглядит следующим образом:
функция asyncinpromise () {
вернуть новое обещание (функция (Resolve) {
settimeout (function () {
var Jsonstr = '{"name": "mt}';
Resolve (Jsonstr);
}, 100);
});
}
asyncinpromise (). Затем (function (val) {
var d = json.parse (val);
Console.log (d.name);
}). Тогда (null, function (err) {
console.log ('show error:' + err.message);
});
// Показать ошибку: неожиданный конец ввода
функция asyncinjquery () {
var d = new $ .deferred ();
settimeout (function () {
var Jsonstr = '{"name": "mt}';
D.resolve (JSonstr);
}, 100);
возврат d.promise ()
}
asyncinjquery (). Затем (function (val) {
var d = json.parse (val);
Console.log (d.name);
}). Тогда (function (v) {
console.log («успех:», v.name);
}, function (err) {
console.log ('show error:' + err.message);
});
// uncaught syntaxError: неожиданный конец ввода
Из этого можно увидеть, что обещание обрабатывает результат функции обратного вызова, которая может запечатлеть исключения во время выполнения функции обратного вызова, но jquery.deferred не может.