Самый прямой ответ на ваш вопрос: вы не можете ждать в браузерном javascript, потому что javascript является строго асинхронным и однопоточным.
Вы можете выбрать (1) написать код обратного вызова, (2) написать код обещания, (3) использовать core.async.
(1) Обратные вызовы. Вместо того, чтобы пытаться «ждать» на сервере для возврата (что вы не можете сделать), передайтекод в качестве обратного вызова:
(defn get-tables [result-atom next]
(ajax/GET "/tables"
{:headers {"Accept" "application/transit+json"}
:handler (fn [response]
(reset! result-atom (vec response))
(next result-atom))})) ; This is the key line
(defn validate-datasource [datasource]
(js/console.log datasource))
(defn get-and-validate-tables [result-atom]
(get-tables result-atom validate-datasource))
Обратите внимание, учитывая, что вы передаете атом в качестве аргумента (и скрываете определение верхнего уровня), вероятно, лучше удалить его полностью и просто иметь handler
передать ответ непосредственно на next
, не связываясь с атомом.
(2) Обещания. Обратные вызовы хороши, если вы делаете только одно, но в тот момент, когда вы пытаетесь соединитьсяболее чем вместе это будет сложно.Вы можете использовать библиотеку promesa для написания кода обещания, который облегчает работу с обратными вызовами.
(defn get-tables
[]
(promesa/promise
(fn [resolve reject]
(ajax/GET "/tables"
{:headers {"Accept" "application/transit+json"}
:handler resolve
:error-handler reject}))))
;; Note, this function returns a promise, so you can call then and catch on it
(get-tables-and-validate []
(-> (get-tables)
(promesa/then (fn [response]
(validate-datasource response)))
(promesa/catch (fn [error]
(js/console.log error)))))
Это хорошо, потому что вы можете объединять в цепочку вызовы, возвращающие обещание, используя вызовы then
.Обработка ошибок также работает хорошо.
3.Core.async. Вы также можете попробовать использовать библиотеку core.async, но я предупреждаю вас, что она содержит много сложности и кода, который вам, вероятно, не нужен.Также довольно неудобно иметь дело с исключениями, и я разбираюсь с угловыми случаями и ошибками, не делая ничего такого сложного.По моему мнению, приведенный выше код обещания является более надежным и простым для исполнения.
Наконец, если проверка атома действительно все, что вам нужно, учтите, что вы можете использовать set-validator!
для своего атома.
(set-validator! tables (fn [atm] (validate-datasource atm)))
Теперь, когда вы обновляете атом tables
, валидатор запускается автоматически.