Думаю, я что-то недопонял с промисами. Вроде как промис - это средство для организации асинхронного кода. Но если сравнить, например, код для AJAX-запроса с промисом и код для AJAX-запроса без промиса, никакой организации кода нет:
по сути reslove()
и reject()
- это всё те же обратные вызовы, которые мы можем сделать и без промиса. Отсюда резонный вопрос: что нам даёт промис?
Пример с промисом:
ajaxRequest = new Promise((resolve, reject) => {
$.ajax({
url: PATH_TO_PHP_SCRIPT,
type: 'GET',
data: dataWillBeSubmitted,
success: response => {
resolve()
},
error: () => {
reject();
}
});
});
ajaxRequest
.then(() => {
// логика успешного запроса
})
.catch(()=>{
// логика ошибки запроса
})
Без промиса (даже короче получается):
$.ajax({
url: PATH_TO_PHP_SCRIPT,
type: 'GET',
data: dataWillBeSubmitted,
success: response => {
successCallback()
},
error: () => {
errorCallback();
}
});
function successCallback(){
}
function errorCallback(){
}
Если использовать промисы только через конструктор - они и правда выглядят немного избыточно. Но даже в таком режиме у них есть важное свойство: обратные вызовы у промиса не могут отработать более одного раза. А еще не позволяют ошибкам распространяться в обратном направлении.
Допустим, у нас есть вот такой код на колбеках, сложившийся исторически:
try {
// ...
if (success) {
successCallback();
} else {
errorCallback();
}
} catch {
if (errorIsNormal) {
successCallback();
} else {
errorCallback();
}
}
Здесь, если внутри successCallback будет ошибка - то в некоторых случаях errorCallback будет сразу же вызван, а в некоторых - не будет. Кроме того, ошибка при выполнении errorCallback тоже может попасть снова в errorCallback - а может и не попасть... Конечно же, так код лучше не писать. Но в больших проектах подобная хренотень может встретиться просто по закону больших чисел.
В случае же с промисами все становится гораздо проще! Если обработчик написан вот так:
request
.then(() => {
// successCallback
})
.catch(()=>{
// errorCallback
})
То ошибка при выполнении successCallback
всегда попадает в errorCallback
, а ошибка из errorCallback
- никогда. Независимо от того, насколько запутан вызываемый код - обработчики будут вызваны только 1 раз и в нужном порядке. С промисами код становится менее хрупким.
Но по-настоящему полезными промисы становятся если использовать их правильно! А правило очень простое: к конструктору промиса можно обращаться только при взаимодействии со старым кодом или в особых случаях.
Ваш пример с ajaxRequest можно переписать вот так:
ajaxRequest = $.ajax({
url: PATH_TO_PHP_SCRIPT,
type: 'GET',
data: dataWillBeSubmitted
});
И все! $.ajax
уже возвращает промис - нет необходимости использовать конструктор! Код уже выглядит проще, не так ли?
Но, допустим, вас не устраивает поведение промисов из jquery (а они ведут себя не совсем как класс Promise), и хочется получить стандартный промис. Это тоже довольно просто:
ajaxRequest = $.ajax({
url: PATH_TO_PHP_SCRIPT,
type: 'GET',
data: dataWillBeSubmitted
});
ajaxRequest = Promise.resolve(ajaxRequest);
Все! Теперь у нас в переменной ajaxRequest
самый обычный промис.
Но допустим, нам надо после получения с сервера ответа его преобразовать. Например, распарсить вложенный json (бывают вот такие кривые серверы). На колбеках это пришлось бы делать вот так:
$.ajax({
url: PATH_TO_PHP_SCRIPT,
type: 'GET',
data: dataWillBeSubmitted,
success: response => {
try {
var data = JSON.parse(response.data);
} catch (ex) {
errorCallback(ex);
return;
}
successCallback(data);
},
error: () => {
errorCallback();
}
});
А вот так это делается на промисах:
ajaxRequest = $.ajax({
url: PATH_TO_PHP_SCRIPT,
type: 'GET',
data: dataWillBeSubmitted
})
.then(response => JSON.parse(response.data));
Промисы помогают избавить от вложенности кода, когда мы один колбек вкладываем в другой и т.д. Воспринимать такой код и работать с ним удобнее.
Промисы придуманы не для создания асинхронного кода, а только для его использования. Например fetch
, вроде он возвращает промис, а вроде это обычный XMLHttpRequest
, а под капотом это XMLHttpRequest
завернутый в промис. Если хотите узнать больше о магии Promis
- советую к прочтению статью от mailru group
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
В приведённом ниже коде machineMonthNumber - это номер месяца от 0 до 11 (в отличие от humanMonthNumber - номер месяца от 1 до 12)Функция validateMachineMonthNumber(machineMonthNumber),...
Настраиваю ckeditor, а точнее его плагин linkХочу сделать так, чтобы при вставке ссылки не прятался протокол (http:// , https:// , ftp://
Когда я нажимаю на кнопку, чтобы высвечивался alert с текстом кнопкиУ меня такой код, это правильно, или надо по-другому прописать?