Теоретично JS обещанията не се различават от обещанията в реалния живот – когато са съчетани с условия, ориентирани към резултата.

Обещанието е действие, което гарантира резултат в бъдеще, резултатът може да бъде очакваният (положителен) и ако нещо се обърка, резултатът ще бъде нещо, което не е било очаквано (отрицателен). Така че, докато изпълняваме обещанието, ние затваряме и условията - какво ще стане, ако:

  1. Ако Майк успее да почисти стаята си (изпълнявайки условието за обещание): Той излиза за футбол !!
  2. Но какво ще стане, ако той не почисти (като не изпълни условието за обещание):той трябва да изпере.

ЗАБЕЛЕЖКА: По отношение на програмирането това поведение представлява асинхронно поведение. Очаква се Майк да почисти стаята си синхронно, но условните действия (обратни повиквания) ще бъдат изпълнени в бъдеще (независимо дали излиза да играе или пере).

Ако приемем, че „Почистване на стаята“ е действие, което води до успех или неуспех. Тогава „Футбол“ и „Пране“ са асинхронните манипулатори, които чакат действието „Почистване на стаята“ да приключи. И в зависимост от това дали резултатът е успех или неуспех, манипулаторите „Футбол“ или „Пране“ ще бъдат изпълнени, АСИНХРОННО!!

Преди да преминем към голяма част от техническите подробности, ако не сте наясно с:

По същество обещанието(ята) е противоотровата на антимодела Callback-hell. Това е нов начин за въвеждане на асинхронни обратни извиквания, без да се налага да се справяте с „пирамидата на гибелта“.

Някои основни неща:

  1. Обещанията трябва да имат основното действие, в нашия пример това беше „Почистване на стаята“. Технически това основно действие е функция, наречена изпълнител.
  2. Сега изпълнителят може да произведе успешни или неуспешни резултати. Манипулаторите — „Футбол“ и „Пране“ са функциите за асинхронно обратно извикване, регистрирани с помощта на then & catch – ще видите повече подробности.
  3. Като разработчик първо трябва да дефинирате функциите изпълнител и манипулатор.
  4. След това влиза(т) обещание(я) — Promises е точно начинът, по който разработчиците трябва да подредят всички тези зависимости в кода по-чисто.
  5. Promise(s) е JS обект, предоставен от стандартната реализация (след ES6), за да организира всички тези зависимости. Ново обещание се създава с помощта на конструктора Promise.

Сега се задълбочете в кода :)

Пример 1: писане на просто обещание

  1. roomCleaning е изпълнителната функция тук — която се изпълнява синхронно от JS.
  2. Приема 2 аргумента разрешаване и отхвърляне,това са само променливите за заместители, които се инициализират от самия JS. Разрешаването представлява успеха, докато отхвърлянето представлява сценария за грешка. Тези манипулатори се извикват асинхронно, след като изпълнителят приключи.
  3. На ред 10 се създава ново обещание чрез предаване на функцията изпълнител като аргумент на конструктора на Promise. Ето как създавате ново обещание. Новият екземпляр се съхранява в променлива promise_1.
  4. На ред 11, promise_1.then е методът, който приема метода за обработка на успеха като аргумент. Какъвто и метод да бъде предаден тук, ще бъде извикан, когато resolve се извика от функцията изпълнител.
promise_1.then((resolveValue)=>{//Success handler, Football
console.log(`Success handler - room claened successfully, football time!!`);
console.log(`resolveValue: ${resolveValue}`);
});

Предаденото обратно извикване след това също приема аргумент (resolveValue), когато извикате resolve(num) във функцията изпълнител, стойността на num се предава като стойност на аргумента resolveValue.

5. По същия начин, обратното извикване, предоставено за функцията catch, се изпълнява от JS, когато се извика reject(error).

В идеалния случай стойността, предадена в отхвърлянето, трябва да представлява обект за грешка, така че JS да предаде този обект на манипулатора на catch — там разработчиците трябва да се справят с грешката.

Пример 2: множество манипулатори могат да бъдат прикачени към едно и също обещание

Множество манипулатори могат да бъдат прикачени към едно и също обещание, което води до множество асинхронни обратни извиквания, регистрирани за изпълнение, когато се извика resolve/reject.

Всички обратни извиквания се изпълняват, но в същия ред, както регистрираните:

В горния пример има два манипулатора, регистрирани и за двата — разрешаване и отхвърляне. И двата манипулатора се изпълняват в същия ред като регистрирания.

Състояния на обещание: чакане, отхвърляне, разрешаване

Нека бързо да поговорим за състоянията на обещанието. Както знаем, Promises са осигурени от JS обекти, които обгръщат и вършат тежката работа по оркестриране на асинхронните повиквания.

Но как разработчиците ще разберат текущото състояние на обещание, тоест дали изпълнителят е завършен или дали е извикан един от манипулаторите. За този обект Promise излага свойството state. Възможни стойности:

  1. В очакване: Ако изпълнителят е в процес на изпълнение.
  2. Разрешено: Ако изпълнителят е приключил с изпълнението и се извиква метод за разрешаване.
  3. Отхвърлено: Ако изпълнителят е приключил с изпълнението и се извиква методът за отхвърляне.

Когато изпълнителят завърши работата, той трябва да извика една от функциите, които получава като аргументи:

  • resolve(value) — за да покаже, че задачата е приключила успешно:
  • задава state на "fulfilled",
  • задава result на value.
  • reject(error) — за да покаже, че е възникнала грешка:
  • задава state до "rejected",
  • задава result на error.

Забележка:

  1. Ако се извика разрешаване в изпълнителя. Повторното извикване на разрешаването няма да окаже влияние — манипулаторът на разрешаване ще бъде извикан само веднъж.
  2. Ако се извика отхвърляне в изпълнителя. Повторното извикване на отхвърлянето няма да окаже влияние — манипулаторът на отхвърляне ще бъде извикан само веднъж.“
  3. След като отхвърлянето/разрешаването е изпълнено, се казва, че обещанието е уредено. Уредено не е официално състояние, а име, дадено за идентифициране дали обещанието е изпълнено с изпълнение на изпълнител и манипулатор.

Свързване на обещания:

Ето някакъв обрат в историята, да предположим, че искате да свържете условията. Например:

  • Ако Майк е в състояние да почисти стаята, тогава той отива на футбол.
  • Във футболен мач, ако вкара гол, тогава като награда получава шанс да посети музикалния концерт. Ако не вкара гол, той почиства кучето си.
  • Ако не може да почисти стаята, тогава той пере.
  • Ако и той не може да довърши прането, трябва да почисти кучето си.
  • Но ако успее да изчисти прането, тогава отива на концерт.

Сега виждате, че условията произвеждат повече условни действия. Технически, асинхронните обратни извиквания (Футбол & Пералня) отново произвеждат допълнителни асинхронни обратни извиквания (MusicConcert & DogCleaning). За да служат на тази цел, обещанията могат да връщат нови обещания — това се нарича верига обещания.

И така, по същество: обещание:

  • Вътрешна изпълнителна функция, можете да извикате метода за разрешаване за успешни сценарии.
  • Или можете да извикате метода за отхвърляне за сценарии за грешка.
  • И ако изходът на тази асинхронна функция трябва да бъде вход към друга асинхронна функция, тогава върнете ново обещание...

Важно нещо, което трябва да отбележите: Погледнете изображението по-горе, ако върнете ново обещание(я) както от манипулатор за разрешаване, така и от манипулатор за отхвърляне, въпреки че връщате два различни екземпляра (използвайки нова ключова дума), но те все още сочат към едно и също обещание екземпляр

Това ще стане ясно от примерния код по-долу:

Ако изпълните горния код в конзолата, ще видите нещо като:

ИЛИ нещо като:

Забележете, че отделните екземпляри на обещание се връщат от манипулаторите за отхвърляне и разрешаване на родителското обещание. Но все пак се отпечатват както Error_success, така и Erro_error, тъй като новите обещания, върнати от манипулаторите, всъщност сочат към един и същ екземпляр на обещание.

Ако това няма смисъл, прочетете това отново:

Важно нещо, което трябва да отбележите: Погледнете изображението по-горе, ако върнете ново обещание(я) както от манипулатор за разрешаване, така и от манипулатор за отхвърляне, въпреки че връщате два различни екземпляра (използвайки нова ключова дума), но те все още сочат към едно и също обещание екземпляр

И погледнете изображението на работния поток за верижно обещание.

Вярвам, че като програмист това е всичко, което трябва да знаете, за да разберете Promises. Ако сте разбрали това, вие сте готови да започнете да изпълнявате Promises!!

Честито кодиране!!