Фронтендщик
رفتن به کانال در Telegram
Все для frontend developer, шуточки, тесты, статьи Администрация/Реклама @vtopua
نمایش بیشتر1 068
مشترکین
اطلاعاتی وجود ندارد24 ساعت
-27 روز
-1330 روز
آرشیو پست ها
1 068
Промис представляет собой объект, в который параметром передается функция, внутри которой нужно размещать наш асинхронный код:
let promise = new
Promise(function()
{
// асинхронный код
});
📌 #instr || Фронтендщик
1 068
Введение в промисы в JavaScript
Вы уже знаете, что использование коллбэк-модели асинхронности легко приводит к ситуации callback hell. Поэтому в JavaScript была введена новая модель под названием промисы (promise). Давайте изучим эту модель.
📌 #instr || Фронтендщик
1 068
Код получился красивый и без callback hell, однако, мы вернулись к двум нашим проблемам: порядок картинок не гарантирован и невозможно поймать момент загрузки всех картинок.
И решения в данной ситуации нет: невозможно запустить цикл, использовать внутри него асинхронную функцию, а потом поймать момент завершения всех функций цикла. Либо вам не нужно ловить этот момент и приведенный выше код вам подойдет либо добро пожаловать в callback hell.
📌 #instr || Фронтендщик
1 068
Асинхронная загрузка картинок в цикле в JavaScript
Пусть пути к картинкам хранятся в массиве:
let arr = ['img1.png',
'img2.png',
'img3.png'];
Мы можем загрузить эти картинки в цикле:
for (let path of arr) {
loadImage(path, function(image,
err) {
document.body.append(image);
});
}
📌 #instr || Фронтендщик
1 068
Мы решили обе описанные проблемы. Однако, получили взамен другую. Пока она еще не сильно видна, но представьте себе, как будет выглядеть наш код, если в нем будет загрузка не трех, а, скажем, десяти картинок, плюс будет добавлена обработка исключений. В результате код станет крайне нечитаемым: сложность кода лавинообразно нарастает при вложенности коллбэков друга. Такая ситуация называется callback hell - ад коллбэков.
📌 #instr || Фронтендщик
1 068
Окей, переделаем код:
loadImage('img1.png',
function(image1,
err1) {
document.body.append(image1);
loadImage('img2.png',
function(image2,
err2) {
document.body.append(image2);
loadImage('img3.png',
function(image3,
err3) {
document.body.append(image3);
console.log('все
картинки
загружены');
});
});
});
📌 #instr || Фронтендщик
1 068
С этим кодом кое-что не так. Дело в том, что картинки будут добавляться в bodyпо мере их загрузки. To есть никто не гарантирует нам, что картинки будут добавлены именно в том порядке, который нам нужен.
Есть еще кое-что. Пусть мы хотим сделать что-нибудь, когда будут загружены все три картинки. В нашем коде мы просто не сможем поймать этот момент, так как все три картинки грузятся независимо.
📌 #instr || Фронтендщик
1 068
Проблема callback hell в JavaScript
Пусть мы хотим с помощью функцииloadImage загрузить три картинки:
loadImage('img1.png',
function(image,
err) {
document.body.append(image);
});
loadImage('img2.png',
function(image,
err) {
document.body.append(image);
});
loadImage('img3.png',
function(image,
err) {
document.body.append(image);
});
📌 #instr || Фронтендщик
1 068
Либо с обработкой исключительной ситуации:
loadImage('image.png',
function(image,
err) {
if (!err) {
document.body.append(image);
} else {
console.log('произошла
ошибка: '
+ err);
}
});
📌 #instr || Фронтендщик
1 068
Мы можем использовать нашу функцию следующим образом:
loadImage('image.png',
function(image,
err) {
document.body.append(image);
// разместим картинку по
загрузке
});
📌 #instr || Фронтендщик
1 068
Пусть в первый параметр нашего коллбэка попадает ссылка на DOM элемент картинки, а во второй - ошибка, если произойдет исключительная ситуация:
loadImage('img.png',
function(image,
err) {
console.log(image, err);
});
📌 #instr || Фронтендщик
1 068
Загрузка картинок через асинхронные коллбэки в JavaScript
Давайте реализуем функцию loadImage, которая будет загружать картинки. Пусть первым параметром эта функция принимает путь к картинке, а вторым - коллбэк, который выполнится, когда картинка будет загружена:
loadImage('img.png',
function() {
// выполнится по загрузке
картинки
});
📌 #instr || Фронтендщик
1 068
Давайте переделаем код нашей функцииmake в соответствии с описанным:
function make(num, callback) {
setTimeout(function() {
let arr = [1, 2, 3, 4, 5];
let err;
if (arr[num] ===
undefined) {
err = 'elem not exists';
// текст ошибки
} else {
err = null; // ошибки нет
}
callback(arr[num], err);
}, 3000);
}
📌 #instr || Фронтендщик
1 068
В коллбэк-подходе с исключениями работают следующим образом: в первый параметр коллбэка отправляют результат, а во второй - ошибку. В этом случае обработка ошибок происходит следующим образом:
make(10, function(res, err) {
if (!err) {
console.log(res);
// ошибки не возникло,
выведем результат
} else {
console.log(err);
// ошибка возникла,
выведем ее текст
}
});
📌 #instr || Фронтендщик
1 068
В нашем случае исключение, возникшее внутриmake или коллбэка, не будет поймано:
try {
make(10, function(res) {
console.log(res);
});
} catch(err) {
// не поймается
}
📌 #instr || Фронтендщик
1 068
Иключения в асинхронных коллбэках в JavaScript
Пусть, если параметром make передан номер несуществующего элемента массива - это исключительная ситуация. Как вы уже знаете, исключения, возникшие внутри асинхронной функции, не могут быть пойманы через try-catch.
📌 #instr || Фронтендщик
1 068
Для примера давайте получим третий элемент массива:
make(3, function(res) {
console.log(res); // третий
элемент массива
});
Давайте переделаем код нашей функции make в соответствии с описанным:
function make(num, callback) {
setTimeout(function() {
let arr = [1, 2, 3, 4, 5];
callback(arr[num]);
// результатом передаем элемент
массива
}, 3000);
}
📌 #instr || Фронтендщик
1 068
Передача параметров в асинхронный коллбэк в JavaScript
Сделаем теперь так, чтобы в асинхронную функцию можно было передавать входные параметры. Пусть для примера в качестве первого параметра функции make мы будем передавать номер того элемента массива, который мы хотим получить в качестве результата.
📌 #instr || Фронтендщик
1 068
Теперь, при передаче коллбэка в вызов функции make мы можем написать в нем параметр - и в этот параметр попадет результат асинхронной операции:
make(function(res) {
console.log(res); // наш
массив
});
📌 #instr || Фронтендщик
1 068
Сделаем так, чтобы массив с результатом передавался в параметр коллбэка:
function make(callback) {
setTimeout(function() {
let res = [1, 2, 3, 4, 5];
callback(res); // передаем
результат
параметром
}, 3000);
}
📌 #instr || Фронтендщик
