JavaScript является асинхронным по определению, что изначально заставляет многих разработчиков на стороне сервера бороться. Многие даже стараются избегать асинхронизма настолько, насколько могут, а не принимать его. Другие заканчивают в беспорядке обратного вызова. Вот где обещания вступают в игру!
Следующий код является типичным фрагментом кода JavaScript. Вызывается некоторая асинхронная функция, передающая реализацию обратного вызова функции в качестве точки подключения для обработки данных после их получения.
// call getData which asynchronously loads the data from somewhere getData(function(result){ // do something meaningful with result });
Хотя этот пример выглядит красиво и просто, он может быстро превратиться в полный беспорядок. Предположим, например, что вам нужно получить некоторые данные из разных бэкэнд-API для их последующей обработки. Вы можете написать код так:
getPeople(function(peopleResult){ getAddresses(function(addressResult){ // use peopleResult and addressResult for further elaboration }); });
Проблемы с этим кодом:
addresses
people
в нашем примере не зависит : тем не менее, они извлекаются последовательно, а не параллельно.- Вложение выглядит грязным и трудно читаемым.
Обещания могут помочь здесь.
Обещание представляет возможный результат асинхронной операции. Обещания / Спецификация A + (https://promisesaplus.com/)
Например, возьмем API Promise от jQuery, также известный как Отложенный . Код, показанный ранее, может быть переписан как:
var people = getPeople(); var addresses = getAddresses(); $.when(people, addresses).done(function(peopleResult, addressesResult){ // elaborate the data });
Это позволяет приятно сгладить вложенную структуру вызовов. Помимо синхронизации различных асинхронных вызовов, возможность объединения в цепочку является еще одной чрезвычайно мощной концепцией, позволяющей преобразовать это …
$("#testInpt").click(function () { firstCallBack(function (param) { getValues(param, function (result) { alert(result); }); }); });
… в это.
$("#testInpt").clickPromise() // promise-returning function .then(firstCallBack) .then(getValues) .then(alert);
Обратите внимание, как результат одного вызова передается в качестве аргумента следующему.
Книга
PacktPub только что выпустил JavaScript Promises Essentials, где Рами Сариеддин более подробно рассматривает API Promise, обращаясь к обещаниям и используя обещания, как определено в спецификации Promise / A + .
Из книги:
Если мы перечислим свойства, с которыми проще работать с обещаниями, они будут следующими:
- Легче читать, как с использованием более чистых методов подписи
- Это позволяет нам прикрепить более одного обратного вызова к одному обещанию
- Это позволяет передавать значения и ошибки и выводить их в функцию вызывающего
- Это позволяет для цепочки обещаний
Книга охватывает практически все, что нужно разработчику для добавления Promises в его набор инструментов. Вот выдержка из оглавления, просто чтобы дать вам представление.
- Обещания JavaScript — Почему я должен заботиться?
- API Promise и его совместимость
- Цепочка обещаний
- Обработка ошибок
- Обещания в WinJS
- Соедини все вместе — обещания в действии
После представления общей концепции Promise и проблем совместимости, он начинает относиться к мелочам Promises, демонстрируя такие понятия, как цепочка и обработка исключений. Также рассматривается, как они реализованы в WinJS, библиотеке JavaScript от Microsoft для разработки приложений Windows 8 Metro.
Моя любимая часть: когда автор объединяет все концепции в конце книги и создает библиотеку Promise с нуля. Это действительно дает вам возможность заглянуть внутрь, испытать проблемы дизайна и внутренней работы.
Вывод
Обещания обязательно должны быть частью инструментария каждого разработчика. Если вы чувствуете, что еще не поняли их, сходите и почитайте, а еще лучше — пройдитесь по учебникам.
Книга определенно охватывает все, что вам нужно знать, не объясняя конкретную библиотеку Promise, а скорее давая вам общее понимание того, как Promise предназначен для работы. Оттуда будет довольно легко понять различные реализации в jQuery.Deferred, RSVP.js, Q.js или как они все называются.
(Кстати, как только вы узнаете, как работают обещания, вы можете взглянуть на генераторы ES6)