Добре дошли в част 1 от тази поредица за използване на библиотеката Typescript Light Arrow за функционално програмиране в Typescript. В част 1 ще разгледаме типа данни Arrow. В част 2 ще изградим напълно безопасен за типа http сървър.

Аз съм авторът на Light Arrow и проектът все още е в начален стадий, моля, свържете се ако имате обратна връзка, благодаря!

Стрели и обещания

Стрелките са структури от данни, които описват асинхронни операции, които могат да успеят с резултатна стойност R или грешка със стойност E, които зависят от някои зависимости D. На практика много програми или части от програми, които пишем, отговарят на това описание и често обещанията се използват за тази цел. Обещанията обаче имат някои недостатъци.

Нека първо да разгледаме подписа на Promise Type.

Promise‹A› представлява асинхронна операция, която може да успее със стойност от тип A. Но какво да кажем за неуспех? това не е представено в сигнатурата на типа, така че трябва да погледнем вътре в изпълнението на нашето конкретно обещание и да определим какви типове трябва да обработва нашият манипулатор на catch error. Обещанията също се оценяват внимателно и не са референтно прозрачни, което може да причини проблеми, когато преработваме. Референтната прозрачност означава, че можем да заменим всички изрази в нашата програма със стойностите, върнати от тези изрази, без да променяме поведението на програмата. За повече относно потенциални проблеми с Promises вижте тази статия.

Стрелки

Стрелките имат редица предимства пред Promises, включително референтна прозрачност, въведени грешки и вградени възможности за инжектиране на зависимости. Всеки от тях е разгледан по-подробно по-долу. Стрелките имат откриваем „плавен“ верижно-способен API, подобно на родните Promises и Arrays. За да видите списък с пълния API на Arrow, вижте сайта за документация.

По-общо казано, отколкото просто асинхронни операции, Arrows може да се използва за моделиране на синхронни или асинхронни странични ефекти и да ги композира заедно по безопасен тип начин, без действително да извършва странични ефекти, поради тази причина структури от данни като Arrow са известни също като „функционални ефекти“ . За тези, които са запознати с функционалното програмиране, Arrows са един вид ReaderTaskEither.

Стрелките по същество могат да се разглеждат като полезни обвивки около функционалния тип
D => Promise<Either<E, R>>, които правят работата с такива типове по-удобна и предоставят помощни методи за композируемост и удобство. За преобразуване на съществуващи типове данни в стрелки има няколко осигурени draw функции, които правят това по-лесно. Можем също така да construct стрелки, както бихме направили за обещания, използващи new Promise, също така по желание да посочим обратно извикване „подреждане“ (напр. за изчистване на изчаквания), вижте тук за примери.

Нека сега да разгледаме някои от предимствата, които споменах с примери. В примерите всички типове са изведени, но са написани само за демонстрационни цели.

Обработка на грешки

Стрелките използват типа данни Either, за да активират безопасно обработване на грешки от централизиран тип. Чрез проследяване на типа грешка можем да знаем от сигнатурата на типа как нашата програма може да се провали и да покрием всички случаи във функцията за обработка на грешки, която предаваме на метода run (подобно на catch манипулатор, който можем да добавим в края на обещание).

Референтна прозрачност

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

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

Инжектиране на зависимост

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

Съставимост

Стрелките са много композируеми чрез техните различни методи (вижте документацията за всички тях). Методите orElse и andThen също се предоставят като комбинаторни функции, които приемат n брой стрелки. orElse може да се използва за „хоризонтална“ композиция, като например изграждане на маршрути на експресно приложение. andThen може да се използва за „вертикална“ композиция, като промяна на контекста на заявка, например в междинен софтуер за оторизация, където потребителят, който прави заявките, се добавя към контекста за използване от последващ междинен софтуер. Включени са и познати функции като all и race (еквиваленти на стрелки на Promise.all и Promise.race) и повече комбинатори като retry и repeat.

производителност

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

Оперативна съвместимост

Има редица помощни функции за преобразуване на съществуващи типове, включително основни стойности, функции, асинхронни функции, в стрелки. Всички те са изброени в документацията.

Light Arrow има за цел да бъде практична библиотека с малък API, базиран на типа данни Arrow, така че тези, които го използват, да могат да получат много от предимствата на функционалното програмиране без твърде много разходи на теория. За да започнете, вижте документацията тук и инсталирайте npm module. За тези, които се интересуват да научат повече за функционалното програмиране, горещо препоръчвам да започнат с първите няколко глави на отличната книга „Функционално програмиране в Scala“.

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