Долу с обратното извикване по дяволите или как Санта Симплисита обещава да работи

Не е лесно да се пише само за прости неща...

Долу с обратното извикване по дяволите или как работят обещанията?

Публикацията ще е кратка. Всеки, който е писал на 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. Основното е, че сега е ясно какво имат вътре.