Долу с обратното извикване по дяволите или как Санта Симплисита обещава да работи
Не е лесно да се пише само за прости неща...
Долу с обратното извикване по дяволите или как работят обещанията?
Публикацията ще е кратка. Всеки, който е писал на Javascript (особено под Node.js), знае, че езикът е еднопоточен и всички продължителни (блокиращи) операции обикновено се изпълняват във функции от тази форма:
Съответно, ако трябва да извършите няколко действия подред последователно, тогава получавате грозна конструкция:
Особено за мнозина възниква въпросът - какво ще стане, ако има масив от елементи, за всеки от тях трябва да извикате асинхронна функция и да направите нещо важно, когато последният завърши. Очевидно обичайното for вече няма да помогне тук:
Някои се осмеляват да използват рекурсия: извикват doSomething на първия елемент, извикват doSomething рекурсивно на следващия елемент в обратното извикване и го премахват от масива. И така, докато масивът се изпразни. такива обещания работят почти по същия начин. Те ви позволяват да пишете асинхронни функции в удобна серийна форма. Кодът изглежда по следния начин:
Как работи?
Очевидно всяко извикване на then() добавя аргументната функция към опашката от планирани функции, но все още не ги изпълнява. И кога го правят?
- отложена опашка с функции
- обект с метод then() за добавяне на нови функции към опашката
- рекурсивна функция, която изпълнява първата чакаща функция в опашката и чака да завърши
- setTimeout(fn, 0) за изпълнение на рекурсивна функция
Как да разберете кога една функция завършва? Най-лесният начин да направите това е изрично - когато функцията е готова да завърши - оставете я да извика специалната функция next(). Звучи сложно, защото думата „функция“ е толкова често срещана? Сега,погледнете кода:
Тук всичко е както е описано по-горе - опашка, рекурсивна функция, setTimeout и обект с метода then().
В примера на екрана се показва "1", след това след секунда - "2" и "3", след още една секунда - "4" и "5".
Кодът може да бъде компресиран почти до размера на туит (137 байта) - https://gist.github.com/zserge/7021626 Може би дори ще го добавя към 140byt.es.
И тогава можете да накарате next() да приема аргументи - например резултата от функцията и обекта за грешка. И можете да видите съществуващите аналози на Promises/Futures. Основното е, че сега е ясно какво имат вътре.