Clojurescript - Uncaught Error: <! используется не в (Go...) блок
Я в Clojurescript и пытаюсь использовать core.async
чтобы получить результат от встроенной функции Javascript (я в браузере) и условно интегрировать ее в карту.
У меня есть функция для переноса нативного вызова браузера (вдохновленный выступлением Тимоти Болдриджа на core.async, примерно 34 минуты для заинтересованных):
(defn geolocation []
(let [c (chan)
cb (fn [e] (put! c (js->clj e)))]
(if (exists? js/navigator.geolocation)
(.getCurrentPosition js/navigator.geolocation. cb cb)
(put! c {:error "Geolocation is not supported"}))
c))
Я могу использовать это так:
;; this works
(go (.log js/console "RES1 -" (<! (geolocation))))
;; this too (not sure how to print it though)
(go (println "RES2 - " (-> {}
(assoc :test (<! (geolocation))))))
;; this fails... why ?
(go (println "RES3 - " (-> {}
(#(when true
(assoc % :test (<! (geolocation))))))))
Последний пример завершается с ошибкой: Uncaught Error: <! used not in (go ...) block
хотя я думал, что использую такую же структуру.
Что я делаю неправильно?
Примечание: я требую это должным образом от :require-macro
Директива, как описано здесь.
1 ответ
go
макрос возьмет тело, которое ему дано, и преобразует все <!
а также alt!
а также >!
звонки на конечный автомат. Однако это не будет входить в функции:
невозможно использовать для цикла в блоке go из core.async?
Под остановкой трансляции на границах функций я имею в виду следующее: блок go берет свое тело и переводит его в конечный автомат. Каждый звонок
<!
>!
или жеalts!
(и несколько других) считаются переходами конечного автомата, в которых выполнение блока может приостанавливаться. В каждой из этих точек машина превращается в обратный вызов и подключается к каналу. Когда этот макрос достигает формы fn, он прекращает трансляцию. Так что вы можете звонить только<!
изнутри блока go, а не внутри функции внутри блока кода.Это часть магии
core.async
, Безgo
макрос, код core.async очень похож на callback-ад в других языках.