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

How do I extract the body from an HTTP request in Clojure?

我正在发出 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:

如何将此值分配给 letdef

另外,为什么第二个console.log打印null

更新

我现在从使用 reagent 个原子转向 reframe

这是我的组件,成功 GETs 数据,更新重新帧 'database':

(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]))

但这是我从重构数据库中得到的对象:

如您所见,它包含在 Reaction 标签中,我无法再访问正文或 value。我如何访问这些?

我有一个使用试剂模板的小型工作版本。创建一个新项目(假设您安装了 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 将 bootstrap 前端的基础知识,但在我们的例子中它只是调用 mount-root 启动试剂告诉它调用 quote-page 并将结果放在 DOM 中替换 ID 为 app 的元素。

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

  • 一旦 response 可用,我将响应结果存储在名为 api-responseatom 中。这里的关键是原子将暂时不包含任何内容(当请求完成时),然后响应将在其中,试剂将负责检测更改并重新渲染。

  • 最后,quote-page 调用 render-quote 生成标记以在加载时呈现报价或占位符。

为了 运行 整个事情,打开一个终端和 运行 lein run 这将启动默认侦听端口 3000 的 Web 服务器。在另一个终端中,运行 lein figwheel 将为您编译 ClojureScript 代码。一个figwheel已经准备好了,它会启动一个REPL,你可以在你的电脑中打开地址http://0.0.0.0:3000/来查看页面。