(def tables (atom nil))
(defn validateDatasource [datasource]
(get-tables tables)
(js/console.log @tables)
)
(defn get-tables [tables]
(ajax/GET "/tables"
{:headers {"Accept" "application/transit+json"}
:handler #(reset! tables (vec %))}
))
在这里,我在点击按钮时调用 validateDatasource ,并且首次点击它打印为空 .. 但是过了一段时间,如果我再次点击,则会在控制台中打印表格地图。
因此,我想知道如何在继续打印之前等待服务器响应?
答案 0 :(得分:0)
您问题的最直接答案是:您不能在浏览器端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
将响应直接传递给{{1没有弄乱原子。
(2)承诺。如果你只做一件事,回调很好,但是当你试图将多个链接在一起时,它会变得复杂。您可以使用promesa库编写承诺代码,使回调更容易处理。
next
这很好,因为您可以使用对(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)))))
的调用将承诺返回的呼叫链接在一起。错误处理也很有效。
第3。 Core.async。您也可以尝试使用core.async库,但我会警告您它引入了许多您可能不需要的复杂性和代码。处理异常也很尴尬,而且我没有做任何复杂的事情,我已经遇到了极端情况和错误。在我看来,上面的承诺代码更健壮,更容易理解。
最后,如果原子验证确实是您想要的,请注意您可以在原子上使用then
。
set-validator!
现在每当您更新(set-validator! tables (fn [atm] (validate-datasource atm)))
原子时,验证器都会自动运行。