如何在继续下一次ClojureScript调用之前等待服务器响应?

时间:2018-05-13 13:40:04

标签: ajax clojure callback async-await clojurescript

(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 ,并且首次点击它打印为空 .. 但是过了一段时间,如果我再次点击,则会在控制台中打印表格地图。

因此,我想知道如何在继续打印之前等待服务器响应?

1 个答案:

答案 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))) 原子时,验证器都会自动运行。