Въведение в промис в JavaScript
Вече знаете, че използването на callback-модела на асинхронност лесно води до ситуация на callback hell. Затова в JavaScript беше въведен нов модел, наречен промис (promise). Нека изучим този модел.
Промисът представлява обект, в който като параметър се предава функция, вътре в която трябва да поставяме нашия асинхронен код:
let promise = new Promise(function() {
// асинхронен код
});
Както виждате, записах обекта с промиса
в променливата promise. На някое друго
място в кода мога да приложа към тази променлива
метода then, като предам в него функция
с кода, който трябва да бъде изпълнен при
завършване на асинхронния код, написан
при създаването на този промис:
promise.then(function() {
// ще се изпълни при завършване на асинхронния код
});
Звучи объркващо, затова нека разгледаме пример. Нека имам следния асинхронен код:
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
}, 3000);
Нека искам да реша за него нашия основен
проблем на асинхронността: да изпълня някакъв
код след задействане на таймера. При това
не искам да поставям този код в самия таймер
и искам в този код по някакъв начин да попадне резултатът,
написан от мен в променливата result.
В общи линии, ние решавахме този проблем в предишните
уроци чрез callback-и и абонаменти. Нека
сега видим как да го направим чрез промис.
Първо трябва да обвием нашия асинхронен код в промис:
let promise = new Promise(function() {
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
}, 3000);
});
Това обаче не е достатъчно. Ние трябва да укажем изрично, че нашият асинхронен код е завършил. В това ще ни помогне специална функция за завършване, която автоматично попада в първия параметър на функцията, ако е указан:
let promise = new Promise(function(resolve) { // указваме параметър
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
}, 3000);
});
С помощта на функцията за завършване можем явно да укажем на промиса, че асинхронният код е завършил. За това трябва да извикаме тази функция на нужното ни място:
let promise = new Promise(function(resolve) {
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
resolve(); // завършваме промиса
}, 3000);
});
При това, ако искаме да предадем навън някакъв резултат от асинхронния код, можем да го предадем като параметър на нашата функция за завършване:
let promise = new Promise(function(resolve) {
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
resolve(result); // предаваме резултата
}, 3000);
});
Може, разбира се, да се отървем от междинната променлива:
let promise = new Promise(function(resolve) {
setTimeout(function() {
resolve([1, 2, 3, 4, 5]);
}, 3000);
});
Сега на всяко друго място можем да извикаме
метода then на нашия промис:
promise.then(function() {
// ще се задейства при завършване на промиса
});
Резултатът от работата на промиса ще попадне в първия параметър на функцията, ако пожелаем да го укажем:
promise.then(function(result) {
console.log(result); // ще изведе масив с резултата
});
Направете промис, вътре в който има забавяне
от 5 секунди, след което промисът трябва
да се изпълни, като върне като резултат някакъв
текст. Изведете този текст на екрана.