Введение в обещания Javascript

Обещание — это метод, который в конечном итоге производит значение. Это можно рассматривать как асинхронный аналог функции-получателя. Вы можете понять, как это работает, на простом примере:

promise.then(function(value){
// Do something with value
});

JavaScript является только асинхронным в том смысле, что он может выполнять, например, вызовы Ajax. Код перестанет выполняться до тех пор, пока не завершится вызов (успешно или иначе), после чего обратный вызов будет выполняться синхронно. Никакой другой код не будет запущен в этот момент.

Благодаря API Promises разработчики могут избежать множества обратных вызовов (просто обратный вызов или передача обратного вызова не означает, что он асинхронный) для обработки асинхронных взаимодействий, которые теперь можно обрабатывать как любую другую переменную.

Обещания могут заменить асинхронное использование обратных вызовов, и они предоставляют несколько преимуществ по сравнению с ними. Они начинают завоевывать популярность, поскольку все больше и больше библиотек и сред используют их в качестве основного способа обработки асинхронности. С 2013 года обещания изначально поддерживаются в современных браузерах.

Почему я должен использовать обещания

Обещания помогут вам сделать весь сложный асинхронный код проще в обработке, понимании и обслуживании.

Обещания не об агрегации обратных вызовов. Это простая утилита. Обещания касаются чего-то гораздо более глубокого, а именно обеспечения прямого соответствия между синхронными функциями и асинхронными функциями.

Обещания javascript представляют собой следующую замечательную парадигму в программировании на JavaScript, но понять, почему они так хороши, непросто, поэтому, пожалуйста, продолжайте читать.

Создание вашего первого обещания

Чтобы понять концепцию, мы представим наиболее простой способ использования Javascript Promise.

Конструктор Promise принимает один аргумент, обратный вызов (функцию) с двумя параметрами, разрешить и отклонить. Теперь внутри обратного вызова вам нужно выполнить все, что вы хотите сделать асинхронно, наконец, если все работает правильно, вызовите функцию разрешения, в противном случае — функцию отклонения (ошибка).

Создайте свое первое обещание на основе следующего фрагмента:

var myFirstPromise = new Promise(function(resolve,reject){
// Do an asynchronous task here like a fetch or an ajax call
// Whatever you want
// then resolve it or reject it
var accepted = true;
// add some condition to know which to send (success or error)
if(accepted){
resolve("Send this value");
}else{
reject("Send this error");
}
});
myFirstPromise.then(function(successData){
// Outputs : "Send this value"
console.info(successData);
}).catch(function(errData){
// Outputs : "Send this error"
console.error(errData);
});

Все экземпляры обещаний будут иметь затем метод, который позволяет вам что-то делать, когда обещание выполнено. then метод обратного вызова получает результат, данный ему resolve выполнение.

Вы можете прикрепить более одного обратного вызова к обещанию. каждый затем добавленный обратный вызов будет последовательно выполняться в том порядке, в котором они были назначены.

Единственная разница в том, что после первого, то, полученное значение для каждого добавленного затем, будет значение, возвращаемое предыдущим, то т.е.

var anyPromise = new Promise(function(resolve,reject){
resolve("Send this value");
});
anyPromise.then(function(successData){
// Outputs : "Send this value"
console.info(successData);
return "But now, the following then receives this string";
}).then(function(data){
// Outputs "But now, the ...."
console.log(data);
return 1000;
}).then(function(data){
// Outputs 1000
console.log(data);
});

ловить обратный вызов выполняется, когда обещание отклонено reject выполнение. Вы даже можете вместо обратного вызова catch предоставить второй параметр then функция.

myFirstPromise.then(function(data) {
console.log(data);
}, function(err) {
console.error(err);
});

Заметка

Будет сработать только 1 обратный вызов с ошибкой, либо функция как второй параметр функции then, либо обратный вызов catch, не дважды.

Promise.resolve Promise.reject

Иногда по разным причинам вам не нужно повторять асинхронную задачу, то есть ajax-вызов, который извлекает что-то и может быть сохранено в памяти. Вот тогда решимость и отклонение вступают в игру.

Используйте эти методы для возврата результата обещания без использования всего конструктора (выполненного или отклоненного).

var cacheUserAge = {};
function getUserAge(id){
// if user id is in the object
// do not fetch the result from the server
// return the local result instead
if(cacheUserAge[id]){
return Promise.resolve(cacheUserAge[id]);
}
// use Promise.reject to trigger the catch callback
return fetch('api/userage/' + id + '.json')
.then(function(data) {
// save it in the object
cacheUserAge[id] = data;
// return the value to the next then callback
return result;
}).catch(function() {
throw new Error('Could not get age: ' + id);
});
}
// Then use it
var userId = 15;
getUserAge(userId).then(function(age){
alert(age);
});

Заметка

Api fetch возвращает обещание.

Выполнение нескольких обещаний одновременно

API обещаний позволяет одновременно выполнять несколько обещаний, используя Promise.all метод.

Promise.all принимает массив обещаний и создает обещание, которое выполняется, когда все они успешно выполнены. Вы получаете массив результатов (независимо от того, какие обещания были выполнены) в том же порядке, что и обещания, которые вы передали.

var firstPromise = new Promise(function(resolve,reject){
resolve("First value");
});
var otherPromise = new Promise(function(resolve,reject){
resolve("Other value");
});
var toFulfill = [firstPromise,otherPromise];
// Outputs ["First value","Other value"]
Promise.all(toFulfill).then(function(arrOfResults){
console.info(arrOfResults);
});

Заметка

Добавьте обратный вызов catch в оператор Promise.all для обнаружения ошибок. Если любое из заданных обещаний в массиве не выполняется, затем обратный вызов не будет вызван, но пойманные.

Promise.race

Да, буквальная гонка между обещаниями. Эта функция противоположна Promise.all, потому что она возвращает только результат (или отклонение) первого выполненного обещания, остальные будут игнорироваться.

Замечания:

Если вы знаете, как эта функция может быть полезна в производстве, пожалуйста, поделитесь ею в поле для комментариев.

var p1 = new Promise(function(resolve, reject) {
setTimeout(function() { resolve('p1!'); }, 5000);
});
var p2 = new Promise(function(resolve, reject) {
setTimeout(function() { resolve('p2!'); }, 10000);
});
// Let's run
Promise.race([p1, p2]).then(function(winner) {
// Outputs p1!
console.log('The winner is: ', winner);
}).catch(function(one, two) {
console.log('Catch: ', one);
});

Кросс-браузерная поддержка

API Promise доступен начиная с Chrome 32, Opera 19, Firefox 29, Safari 8 Microsoft Edge, обещания включены по умолчанию на них.

Polyfill

Как упоминалось ранее, введение API не распространяется на устаревшие браузеры, но есть много реализаций полизаполнения, доступных для использования. . Большая часть полизаполнения охватывает все возможные сценарии API, однако в IE9 есть ограничение, которое может быть легко решено с использованием другого синтаксиса.

catch это зарезервированное слово в IE<9, meaning выдает синтаксическую ошибку. Чтобы обойти это, вы можете использовать строку для доступа к свойству, как показано в следующем примере:

promise['catch'](function(err) {
// ...
});
// Or just use the second paramer of then instead of using catch
promise.then(undefined, function(err) {
// ...
});

Заметка

Такая методика уже предусмотрена большинством распространенных минификаторов, что делает полученный код безопасным для старых браузеров и производства. Однако, чтобы предотвратить любую возможную несовместимость, используйте второй параметр функции then вместо использования catch.

Существует множество реализаций обещаний, доступных для разработчиков. Например, jQuery’s Отложенный, от Microsoft WinJS.Promise, when.js, Q, а также dojo.Deferred. Однако имейте в виду, что вы используете его, так как не все они следуют стандартам, реализация jQuery не совсем соответствует спецификации Promises / A так, как это делает большинство других реализаций.

Начните использовать обещания сейчас, получайте удовольствие!

Ссылка на основную публикацию
Adblock
detector