如何在Clojure中从HTTP请求中提取正文?

时间:2019-09-08 16:19:22

标签: clojurescript

我正在发出HTTP请求:

(defn main-panel []

  (def API-URL "https://api.chucknorris.io/jokes/random")

  (defn getFileTree []
    (go (let [response (<! (http/get API-URL
                                     {:with-credentials? false
                                      :headers {"Content-Type" "application/json"}}))]
          (:status response)
          (js/console.log (:body response))))) ; prints a very complex data structure

  (go
    (let [result (<! (getFileTree))]
      (.log js/console (:body result)))) ; prints null

    :reagent-render
    (fn []
      [:h1 "kjdfkjndfkjn"]))

但是我不能在返回的对象数组项13中出现“笑话”:

enter image description here

如何将此值分配给letdef

此外,为什么第二个console.log打印null?谢谢。

更新

我现在正在从使用reagent原子转移到reframe

这是我的组件,成功GET的数据,更新了重新构架的“数据库”:

(defn main-panel []

  (def API-URL "https://api.chucknorris.io/jokes/random")
  (def request-opts {:with-credentials? false})

  (defn getFileTree []
    (go (let [response (<! (http/get API-URL request-opts))]
          (re-frame/dispatch [:update-quote response]))))

  (defn render-quote []
    (println (re-frame/subscribe [::subs/quote])) ;successfully prints API data as in screenshot below
    (fn []
      (let [quote-data (re-frame/subscribe [::subs/quote])
            quote-text (if quote-data (:value quote-data) "...loading...")]
        [:div
         [:h3 "Chuck quote of the day"]
         [:em quote-text]])))

  (fn []
    (getFileTree)
    [render-quote]))

但这是我从重新框架数据库中获得的对象: enter image description here

如您所见,它包裹在Reaction标签中,我无法再访问正文或value。我该如何访问那些?预先感谢。

1 个答案:

答案 0 :(得分:1)

我使用试剂模板的版本较小。使用以下命令创建一个新项目(假设您已安装Leiningen):lein new reagent chuck。这将创建一个具有很多依赖项的项目,但是它是开箱即用的。

接下来,在src/cljs/chuck/core.cljs处编辑文件并对其进行编辑,使其看起来如下所示:

(ns chuck.core
  (:require-macros [cljs.core.async.macros :refer [go]])
  (:require [reagent.core :as reagent :refer [atom]]
            [cljs-http.client :as http]
            [cljs.core.async :refer [<!]]))

(def api-url "https://api.chucknorris.io/jokes/random")
(def request-opts {:with-credentials? false
                   :headers {"Content-Type" "application/json"}})

(def api-response (atom nil))

(defn get-quote []
  (go
    (let [response (<! (http/get api-url request-opts))]
      (println response)
      (reset! api-response response))))

(defn render-quote []
  (fn []
    (let [quote-data (:body @api-response)
          quote-text (if quote-data (:value quote-data) "...loading...")]
      [:div
       [:h3 "Chuck quote of the day"]
       [:em quote-text]])))

(defn quote-page []
  (fn []
    (do
      (get-quote)
      [:div
       [:header
        [render-quote]]
       [:footer
        [:p "footer here"]]])))

;; -------------------------
;; Initialize app

(defn mount-root []
  (reagent/render [quote-page] (.getElementById js/document "app")))

(defn init! []
  (mount-root))

我将解释相关内容:

  • init将引导前端的基础知识,但在我们的示例中,它只是调用mount-root,这开始使试剂告诉它调用quote-page并将结果放入DOM将ID替换为app的元素。

  • quote-page调用get-quote,这将使用cljs-http库来调用API。我不是在这里检查错误,而是基本上在请求完成时(成功或错误),它将从通道读取结果(使用<!)并将响应放入response中。关键是响应是一个嵌套ClojureScript映射,您可以检查该映射以检查结果是否成功。请注意,我还使用println而不是JS interop(.log js/console xxx)打印结果,因为console.log将显示嵌套映射的实现方式的内部细节,这与这种情况。

  • 一个response可用,我将响应结果存储在名为atom的{​​{1}}中。此处的关键是原子(在请求完成时)将不包含任何内容,然后响应将在其内部,并且试剂将负责检测更改并重新呈现。

  • 最后,api-response调用quote-page会生成标记,以便在引用或占位符加载时呈现它。

firefox console screenshot

要运行全部程序,请打开终端并运行render-quote,这将默认启动Web服务器侦听端口3000。在另一个终端中,运行lein run,它将为您编译ClojureScript代码。准备就绪一个小齿轮,它将启动REPL,您可以在计算机上打开地址http://0.0.0.0:3000/来查看页面。