Увядзенне ў промісы ў JavaScript

Вы ўжо ведаеце, што выкарыстанне колбэк-мадэлі асінхроннасці лёгка прыводзіць да сітуацыі callback hell. Таму ў JavaScript была ўведзена новая мадэль пад назвай промісы (promise, абяцанне). Давайте вывучым гэтую мадэль.

Проміс уяўляе сабой аб'ект, у які параметрам перадаецца функцыя, унутры якой трэба размяшчаць наш асінхронны код:

javascriptlet promise = new Promise(function() {
  // асінхронны код
});

Як вы бачыце, я запісаў аб'ект з промісам у зменную promise. У нейкім іншым месцы кода я магу прымяніць да гэтай зменнай метад then, перадаўшы ў яго функцыю з кодам, які павінен быць выкананы па завяршэнні асінхроннага кода, напісанага пры стварэнні дадзенага проміса:

javascriptpromise.then(function() {
  // выканаецца пры завяршэнні асінхроннага кода
});

Гучыць заблытана, таму давайте паглядзім на прыклад. Хай у мяне ёсць вось такі асінхронны код:

javascriptsetTimeout(function() {
  let result = [1, 2, 3, 4, 5];
}, 3000);

Хай я хачу вырашыць для яго нашу асноўную задачу асінхроннасці: выканаць некаторы код пасля спрацоўвання таймера. Пры гэтым я не хачу размяшчаць гэты код у самым таймеры і хачу, каб у гэты код як-трапіў вынік, напісаны мною ў зменнай result. Увогуле, мы вырашалі гэтую задачу ў папярэдніх уроках праз колбэкі і падпіскі. Давайте цяпер паглядзім, як гэта зрабіць праз промісы.

Для пачатку трэба абгарнуць наш асінхронны код у проміс:

javascriptlet promise = new Promise(function() {
  setTimeout(function() {
    let result = [1, 2, 3, 4, 5];
  }, 3000);
});

Гэтага, аднак, не дастаткова. Мы павінны у яўным выглядзе паказаць, што наш асінхронны код завяршыўся. У гэтым нам дапаможа спецыяльная функцыя завяршэння, аўтаматычна якая трапляе ў першы параметр функцыі, калі ён паказаны:

javascriptlet promise = new Promise(function(resolve) { // паказваем параметр
  setTimeout(function() {
    let result = [1, 2, 3, 4, 5];
  }, 3000);
});

З дапамогай функцыі завяршэння мы можам яўна паказаць промісу, што асінхронны код завяршыўся. Для гэтага мы павінны выклікаць гэтую функцыю ў патрэбным нам месцы:

javascriptlet promise = new Promise(function(resolve) {
  setTimeout(function() {
    let result = [1, 2, 3, 4, 5];
    resolve(); // завяршаем проміс
  }, 3000);
});

Пры гэтым, калі мы хочам перадаць вонкі які-небудзь вынік асінхроннага кода, мы можам перадаць яго параметрам нашай функцыі завяршэння:

javascriptlet promise = new Promise(function(resolve) {
  setTimeout(function() {
    let result = [1, 2, 3, 4, 5];
    resolve(result); // перадаем вынік
  }, 3000);
});

Можна, вядома ж, пазбавіцца ад прамежкавай зменнай:

javascriptlet promise = new Promise(function(resolve) {
  setTimeout(function() {
    resolve([1, 2, 3, 4, 5]);
  }, 3000);
});

Цяпер у любым іншым месцы мы можам выклікаць метад then нашага проміса:

javascriptpromise.then(function() {
  // спрацуе па завяршэнню проміса
});

Вынік працы проміса трапіць у першы параметр функцыі, калі мы пажадаем яго паказаць:

javascriptpromise.then(function(result) {
  console.log(result); // вывядзе масіў з вынікам
});
Задание 1

Зрабіце проміс, унутры якога будзе затрымка ў 5 секунд, пасля якой проміс павінен выканацца, сваім вынікам вярнуўшы які-небудзь тэкст. Вывядзіце гэты тэкст на экран.