Изпълнение на обещания в JavaScript

Снимка на Джошуа Станард на Unsplash

Нещото, което най-много обичам в програмирането, е аха! момент, когато започнете да разбирате напълно понятие. Въпреки че може да отнеме много време и да не се полагат малко усилия, за да стигнете до там, със сигурност си заслужава.

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

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

Надявам се, че тази статия ще ви помогне да се справите с изпълнението на обещанията и в JavaScript.

Ще се съсредоточим върху това как да приложим ядрото на обещанието според спецификацията Promises / A + с няколко метода на API на Bluebird. Ние също ще използваме TDD подхода с Jest.

TypeScript също ще е полезен.

Като се има предвид, че тук ще работим върху уменията за прилагане, предполагам, че имате някакво основно разбиране за това какво са обещанията и неясен усет за това как работят. Ако нямате, тук е чудесно място да започнете.

Сега, след като сме излезли от това, продължете и клонирайте хранилището и нека започнем.

Ядрото на обещанието

Както знаете, обещанието е обект със следните свойства:

Тогава

Метод, който привързва обработчик към нашето обещание. Той връща ново обещание със стойността от предишното, картографирано по един от методите на обработващия.

Дръжки

Масив от обработващи файлове, прикачени дотогава. Манипулаторът е обект, съдържащ два метода onSuccess и onFail, като и двата се предават като аргументи на това (onSuccess, onFail).

състояние

Обещание може да бъде в едно от трите състояния: разрешено, отхвърлено или висящо.

Решен означава, че или всичко вървеше гладко и ние получихме стойността си, или хванахме и обработихме грешката.

Отхвърлен означава, че или сме отхвърлили обещанието, или е била изхвърлена грешка и не сме я спазили.

Изчакване означава, че все още не е извикан нито методът за разрешаване, нито отхвърляне и ние все още чакаме стойността.

Терминът „обещанието е изпълнено“ означава, че обещанието е или разрешено, или отхвърлено.

стойност

Стойност, която сме разрешили или отхвърлили.

След като стойността е зададена, няма начин да я промените.

Тестване

Според подхода на TDD, ние искаме да напишем нашите тестове, преди да дойде действителният код, така че нека направим точно това.

Ето тестовете за нашето ядро:

Изпълнение на нашите тестове

Горещо препоръчвам да използвате разширението Jest за Visual Studio Code. Той провежда нашите тестове на заден план за нас и ни показва резултата точно между редовете на нашия код като зелени и червени точки съответно за преминали и неуспешни тестове.

За да видите резултатите, отворете конзолата "Изход" и изберете раздела "Jest".

Можем също да стартираме нашите тестове, като изпълним следната команда:

тест за изпълнение на npm

Независимо от това как провеждаме тестовете, можем да видим, че всички те се връщат отрицателни.

Нека да променим това.

Изпълнение на ядрото на Promise

конструктор

Нашият конструктор приема обратен сигнал за обратно извикване.

Ние наричаме това обратно извикване с this.resolve и this.reject като аргументи.

Обърнете внимание, че обикновено бихме обвързали this.resolve и this.reject с това, но тук вместо това използвахме метода на класовата стрелка.

setResult

Сега трябва да зададем резултата. Моля, не забравяйте, че трябва да боравим с резултата правилно, което означава, че ако той даде обещание, първо трябва да го разрешим.

Първо проверяваме дали състоянието не е в очакване - ако е, тогава обещанието вече е изпълнено и не можем да му присвоим нова стойност.

Тогава трябва да проверим дали дадена стойност е подлежаща на поддръжка. Казано по-просто, anable е обект, който тогава е метод.

По конвенция, подвижният трябва да се държи като обещание. Така че за да получим резултата, ще се обадим тогава и ще предадем като аргументи this.resolve и this.reject.

След като Thenable се уреди, той ще извика един от нашите методи и ще ни даде очакваната стойност без обещание.

Така че сега трябва да проверим дали даден обект е подлежащ на поддръжка.

Важно е да осъзнаем, че нашето обещание никога няма да бъде синхронно, дори ако кодът вътре в обратния разговор е.

Ще забавим изпълнението до следващата итерация на цикъл на събитията, като използваме setTimeout.

Сега единственото, което ни остава, е да определим нашата стойност и статус и след това да изпълним регистрираните манипулатори.

executeHandlers

Отново се уверете, че държавата не е в очакване.

Състоянието на обещанието диктува коя функция ще използваме.

Ако е решено, трябва да изпълним onSuccess, в противен случай - onFail.

Нека сега изчистим нашия масив от обработващи файлове, за да бъдем в безопасност и да не изпълняваме нищо случайно в бъдеще. Един манипулатор може да бъде прикрепен и изпълнен по-късно по всяко време.

И това е, което трябва да обсъдим по-нататък: начин да прикачим нашия манипулатор.

attachHandler

Наистина е толкова просто, колкото изглежда. Просто добавяме манипулатор към масива на манипулаторите и го изпълняваме. Това е.

Сега, за да се събере всичко това, трябва да приложим тогавашния метод.

тогава

След това връщаме обещание и в обратния разговор прикачваме манипулатор, който след това се използва, за да изчака текущото обещание да бъде уредено.

Когато това се случи, ще бъде изпълнен onSuccess или onFail на обработващия и ние ще продължим съответно.

Едно нещо, което трябва да запомните тук, е, че нито един от предадените тогава обработвачи не се изисква. Важно е обаче да не се опитваме да изпълним нещо, което може да е неопределено.

Също така, в onFail, когато обработващият е преминал, всъщност решаваме върнатото обещание, защото грешката е обработена.

улов

Уловът всъщност е просто абстракция над тогавашния метод.

Това е.

накрая

И накрая е просто абстракция от това да правиш тогава (накраяCb, накраяCb), защото всъщност не се интересува от резултата от обещанието.

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

ToString

Той просто ще върне низ [обект PQ].

След като изпълниха ядрото на нашите обещания, сега можем да приложим някои от споменатите по-горе методи на Bluebird, което ще направи работата с обещанията по-лесна за нас.

Допълнителни методи

Promise.resolve

Как трябва да работи.

Promise.reject

Как трябва да работи.

Promise.all

Как трябва да работи.

Вярвам, че внедряването е доста просто.

Започвайки от collection.length, ние отброяваме с всеки tryResolve, докато стигнем до 0, което означава, че всеки елемент от колекцията е разрешен. След това разрешаваме новосъздадената колекция.

Promise.any

Как трябва да работи.

Просто изчакваме първата стойност да се разреши и да я върнем обещано.

Promise.props

Как трябва да работи.

Повтаряме ключове на предадения обект, разрешавайки всяка стойност. След това присвояваме стойностите на новия обект и разрешаваме обещание с него.

Promise.prototype.spread

Как трябва да работи.

Promise.delay

Как трябва да работи.

Използвайки setTimeout, ние просто забавяме изпълнението на функцията за разрешаване с дадения брой милисекунди.

Promise.prototype.timeout

Как трябва да работи.

Този е малко труден.

Ако setTimeout се изпълни по-бързо, отколкото в нашето обещание, той ще отхвърли обещанието с нашата специална грешка.

Promise.promisify

Как трябва да работи.

Прилагаме към функцията всички предадени аргументи, плюс - като последен - връщаме грешката първа обратна връзка.

Promise.promisifyAll

Как трябва да работи.

Итератираме ключовете на обекта и обещаваме неговите методи и добавяме към всяко име на метода дума Async.

Обобщавайки

Представени тук бяха само няколко сред всички методи на Bluebird API, така че силно ви съветвам да проучите, да си поиграете и да опитате да внедрите останалите.

В началото може да изглежда трудно, но не се обезкуражавайте - би било безполезно, ако беше лесно.

Благодаря ви много за четенето! Надявам се, че сте намерили тази статия за информативна и че тя ви помогна да разберете концепцията за обещанията и че от сега нататък ще се чувствате по-удобно, като ги използвате или просто пишете асинхронен код.

Ако имате въпроси или коментари, не се колебайте да ги поставите в секцията за коментари по-долу или да ми изпратите съобщение.

Вижте моите социални медии!

Присъединете се към моя бюлетин!

Първоначално публикувано на www.mcieslar.com на 4 август 2018 г.