Эта статья в основном популяризирует использование обещаний.
В течение долгого времени JavaScript всегда был асинхронно в форме обратного вызова, и механизм обратного вызовов в области передового развития почти глубоко укоренился в сердцах людей. При разработке API, будь то производитель браузеров, разработчик SDK или автор различной библиотеки, они в основном следуют рутине обратного вызова.
В последние годы, с постепенной сроком погашения модели разработки JavaScript, родилась спецификация CommonJS, включая предложение спецификации перспективы. Обещание полностью изменило написание асинхронного программирования JS, сделав асинхронное программирование очень простым для понимания.
В модели обратного вызова, мы предполагаем, что асинхронная очередь должна быть выполнена, и код может выглядеть так:
LOADIMG ('a.jpg', function () {loadImg ('b.jpg', function () {loadimg ('c.jpg', function () {console.log ('все готово!');});});});Это то, что мы часто называем пирамидой. Когда существует много асинхронных задач, поддержание большого количества обратных вызовов будет катастрофой. В настоящее время Node.js очень популярен. Кажется, что многие команды хотят использовать его, чтобы сделать что -то, чтобы ладить с «модой». После общения с одноклассником операции и технического обслуживания они также планировали использовать Node.js, чтобы что -то сделать, но когда они думают о слоях обратных вызовов JS, они обескуражены.
Хорошо, чепуха закончилась, давайте доберемся до темы.
Обещание может быть знакомо со всеми, потому что спецификация перспектива была выпущена в течение долгого времени, и обещание было включено в ES6, а более высокие версии браузеров Chrome и Firefox выполнили обещание, но в настоящее время меньше API -интерфейсов, чем популярная библиотека классов перспектив.
Так называемое обещание можно буквально понимать как «обещание», что означает, что вызовы B, B возвращает «обещание» в A, а затем A может написать это при написании плана: когда B возвращает результат мне, PERSECTIONS S1. Напротив, если B не дает желаемого результата по какой -то причине, то выполняет план экстренной помощи S2, так что все потенциальные риски находятся в пределах контролируемого диапазона А.
Приведенное выше предложение переводится в код, аналогичный:
var resb = b (); var runa = function () {resb.then (execs1, exec2);}; runa ();Просто глядя на вышеупомянутую строку кода, кажется, что нет ничего особенного. Но реальность может быть гораздо сложнее, чем эта. Чтобы выполнить одну вещь, может полагаться на реакцию более чем одного человека B. Это может потребовать одновременно спросить нескольких людей, а затем реализовать следующий план после получения всех ответов. Последний перевод в код может выглядеть так:
var resb = b (); var resc = c (); ... var runa = function () {reqb .Then (resc, execs2) .then (resd, exec3) .then (rese, execs4) ... .Then (execs1);}; runa ();Здесь различные механизмы обработки используются, когда каждый запрос, отвечающий, которые не соответствуют ожиданиям. На самом деле, спецификация перспектива не требует этого, и вы даже не можете ничего не делать (то есть не пройти во втором параметре тогда) и не обработать его равномерно.
Хорошо, давайте узнаем спецификации обещания/A+:
then метод (можно сказать, что тогда является ядром обещания), а затем должен вернуть обещание. Тогда одного и того же обещания можно назвать несколько раз, а порядок выполнения обратных вызовов согласуется с порядком, когда они определеныКак видите, в спецификации обещания не так много контента, поэтому вы можете попытаться реализовать следующее обещание самостоятельно.
Ниже приводится простая реализация обещания, которое я ссылался на многие библиотеки обещаний. Пожалуйста, перейдите в Propisea в коде.
Краткий анализ идей:
Обещание конструктора принимает resolver функции, который можно понимать как передачу асинхронной задачи. Резольвер принимает два параметра, один из них является обратным вызовом, когда успешный, а другой - обратный вызов при сбое. Эти два параметра равны параметрам, проходящим тогда.
Второе - это реализация тогда. Поскольку обещание требует, чтобы затем вернуть обещание, при его вызове будет создано новое обещание, которое будет повешено на _next текущего обещания. Несколько вызовов одного и того же обещания только вернет ранее сгенерированное _next .
Поскольку два параметра, принятые тогдашним методом, являются необязательными, и нет никаких ограничений на тип, это может быть функция, конкретное значение или другое обещание. Вот конкретная реализация тогда:
Rape.prototype.then = function (Resolve, dize) {var Next = this._Next || (this._next = propect ()); var status = this.status; var x; if ('wounding' === status) {isfn (resolve) && this._resolves.push (Resolve); isfn (отклонить) && this._rejects.push (отклонить); вернуться Далее; } if ('Resolved' === Status) {if (! isfn (Resolve)) {next.Resolve (Resolve); } else {try {x = Resolve (this.value); RESOLVEX (Далее, x); } catch (e) {this.reject (e); }} вернуть следующее; } if ('отклонить' === status) {if (! isfn (dreject)) {next.reject (dize); } else {try {x = deact (this.Reason); RESOLVEX (Далее, x); } catch (e) {this.reject (e); }} вернуть следующее; }};Здесь, затем упростила реализацию других библиотек Class Class, и реализация гораздо сложнее, чем эта, и она также имеет больше функций. Например, существует третий параметр - уведомление, которое указывает на текущий прогресс обещания, который очень полезен при загрузке файлов проектирования и т. Д. Обработка различных параметров тогда является наиболее сложной частью. Заинтересованные студенты могут ссылаться на реализацию других типов библиотек обещаний.
На основании этого необходимо по крайней мере два метода, а именно, чтобы завершить преобразование состояния обещания от ожидания в разрешение или отклонено, и выполнить соответствующую очередь обратного вызова, а именно методы resolve() и reject() .
На данный момент было разработано простое обещание. Ниже приведены простые реализации следующих двух обещанных функций:
Функция Sleep (ms) {return function (v) {var p = propect (); setTimeout (function () {p.Resolve (v);}, ms); возврат P; };}; function getImg (url) {var p = resport (); var img = новое изображение (); img.onload = function () {p.resolve (this); }; img.onerror = function (err) {p.reject (err); }; img.url = url; вернуть p;}; Поскольку конструктор перспектива принимает асинхронную задачу в качестве параметра, также можно назвать getImg :
функция getImg (url) {return propect (function (Resolve, dize) {var img = new image (); img.onload = function () {Resolve (this);}; img.onerror = function (err) {deact (err);}; img.url = url;});};Затем (момент, когда свидетельствует о чуде), предположим, что существует требование BT, чтобы реализовать это: Получите асинхронно конфигурацию JSON, анализируйте данные JSON и получите изображения внутрь, а затем загрузите изображения последовательно и дайте эффект загрузки, когда не загружается изображение.
Функция addImg (img) {$ ('#list'). find ('> li: last-mild'). html (''). Append (img);}; function prepend () {$ ('<li>') .html ('загрузка ...') .appendto ($ ('#stist'));); getData ('map.json') .Then (function (data) {$ ('h4'). html (data.name); return data.list.reduce (function (promise, item) {return promise .then (premend) .then (sleep (1000). Special.Resolve ());Сон здесь только что добавлен, чтобы увидеть эффект, вы можете нажать, чтобы просмотреть демонстрацию! Конечно, пример Node.js можно просмотреть здесь.
Здесь статический метод Promise.resolve(v) просто возвращает обещание с V в качестве положительного результата. V не может быть передано, или это может быть функция или объект или функция, содержащую then метод (то есть затем).
Подобные статические методы включают Promise.cast(promise) , который генерирует обещание с обещанием в качестве положительного результата;
Promise.reject(reason) генерирует обещание с разумом в качестве негативного результата.
Наши фактические сценарии использования могут быть очень сложными и часто требуют, чтобы несколько асинхронных задач были выполнены, параллельно или последовательно. В настоящее время вы можете сделать различные расширения для обещания, такие как реализация Promise.all() , принятие очереди обещаний и ожидание их завершения, прежде чем продолжить, и, например, Promise.any() , когда любая из очередей обещания будет в состоянии завершения, следующая операция будет запускается.
Вы можете обратиться к этой статье в HTML5Rocks JavaScript обещаниях. В настоящее время усовершенствованные браузеры, такие как Chrome и Firefox, имеют встроенные объекты Promise, предоставляющие больше операционных интерфейсов, таких как Promise.all() , который поддерживает проход в массиве обещаний, а затем выполняется, когда все обещания выполняются. Существует также более дружелюбный и мощный захват исключений, которого должно быть достаточно, чтобы иметь дело с ежедневным асинхронным программированием.
Самые популярные библиотеки JS сегодня выполнили обещание в различных степени, таких как Dojo, jQuery, Zepto, When.js, Q и т. Д., Но большинство обнаженных объектов Deferred . Взяв jQuery (Zepto аналогичный) в качестве примера, реализуйте вышеуказанный getImg() :
function getimg (url) {var def = $ .deferred (); var img = новое изображение (); img.onload = function () {def.resolve (this); }; img.onerror = function (err) {def.reject (err); }; img.src = url; return def.promise ();}; Конечно, в jQuery многие операции возвращают отложенные или обещания, такие как animate и ajax :
// ajax $ .ajax (непрозрачность ': 0}, 1000) .promise () .Then (function () {console.log (' dode ');}); // ajax $ .ajax (опционы) .Then (успех, неудачный); $. ajax (опционы). $ .ajax (options2)) .Then (function () {console.log ('все сделано.');}, function () {console.error ('там что -то не так.');}); jQuery также реализует методы done() и fail() , которые на самом деле являются ярлыками метода тогдашнего.
Чтобы обрабатывать очередь обещаний, jQuery реализует метод $.when() , и его использование аналогично Promise.all() .
Для других классовых библиотек стоит упомянуть здесь, что когда. Из -за ограничений пространства мы больше не будем его расширять.
Мы видим, что независимо от того, насколько сложна внедрение обещания, его использование очень простое, а организационный код очень ясен. Отныне не нужно пытаться обратно.
Наконец, обещание настолько элегантно! Но обещание решает только проблему глубокого гнездования обратных вызовов. Это генератор, который действительно упрощает асинхронное программирование JavaScript. На стороне Node.js рекомендуется рассмотреть генератор.
Следующая статья, генератор изучения.
github Оригинальный текст: https://github.com/chemdemo/chemdemo.github.io/issues/6