Асинхронное программирование в JavaScript может быть выполнено с использованием следующих методов.
- Обратные вызовы
- Обещания
- Асинхронное ожидание
- Наблюдаемые
В этой статье мы сосредоточимся на обратных вызовах и промисах.
Говорят, что обещания лучше обратных вызовов.
Но многие люди, которые начинают использовать промисы, считают, что между промисами и обратными вызовами нет большой разницы. Это связано с тем, что они рассматривают промисы как обратные вызовы. Эта статья прольет свет на то, как правильно использовать Promise.
Для начала возьмем пример обратных вызовов. Добавьте два числа
function add(a,b,callback){ setTimeout(function(){ callback(a+b) },1) }
Скажем, мы хотим добавить 4 числа, 1,2,3,4. Наша функция добавления принимает только 2 параметра за раз. Таким образом, нам придется сначала сложить два числа, а затем добавить результат к третьему и так далее.
add(1,2,function(result1){ add(result1,3,function(result2){ add(result2,4,function(result3){ console.log(result3); }); }) })
Этот код называется адом обратного вызова. По мере того, как он становится больше, становится очень трудно понимать и управлять этим кодом.
Давайте сделаем то же самое, используя промисы. Допустим, у нас есть еще одна функция addP, которая возвращает обещание, которое разрешается в результате сложения.
function addP(a,b){ return new Promise(function(resolve,reject){ setTimeout(function(){ resolve(a+b); },1) }); }
Используя эту функцию addP, наш код для добавления 4 чисел будет выглядеть так:
addP(1,2).then(function(result1){ addP(result1,3).then(function(result2){ addP(result2,4).then(function(result3){ console.log(result3); }); }); })
Таким образом, даже после использования промисов структура кода остается прежней. Тогда какой смысл использовать обещание. Проблема здесь в том, что мы не используем функцию связывания промисов. Когда мы это сделаем, мы сможем избавиться от ада обратного вызова, как показано ниже.
addP(1,2).then(function(result1){ return addP(result1,3) }).then(function(result2){ return addP(result2,4) }).then(function(result3){ console.log(result3); });
Понимание цепочки промисов
Цепочка работает, потому что then() возвращает другое обещание. Это обещание преобразуется в возвращаемое значение функции обработчика then. Давайте посмотрим на код, чтобы лучше понять.
let p = someAsyncCall(); let thenHandler = function(){ return 10; } let p2 = p.then(thenHandler); p2.then(function(result){ console.log("p2 resolved value :",result); //10 })
В этом случае разрешенное значение p2 будет значением, возвращаемым thenHandler. В случае, если значение, возвращаемое thenHandler, является обещанием, p2 разрешится после того, как это обещание будет разрешено со значением этого обещания.
let p = someAsyncCall(); let thenHandler = function(){ return Promise.resolve(20);//simple way to create a new promise //that will resolve to 20 } let p2 = p.then(thenHandler); p2.then(function(result){ console.log("p2 resolved value :",result); //20 })
В следующей части мы увидим больше различий в обработке ошибок между промисами и обратными вызовами.