如何从 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:
如何将此值分配给 let
或 def
?
另外,为什么第二个console.log打印null
?
更新
我现在从使用 reagent
个原子转向 reframe
。
这是我的组件,成功 GET
s 数据,更新重新帧 '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-response
的 atom
中。这里的关键是原子将暂时不包含任何内容(当请求完成时),然后响应将在其中,试剂将负责检测更改并重新渲染。
最后,quote-page
调用 render-quote
生成标记以在加载时呈现报价或占位符。
为了 运行 整个事情,打开一个终端和 运行 lein run
这将启动默认侦听端口 3000 的 Web 服务器。在另一个终端中,运行 lein figwheel
将为您编译 ClojureScript 代码。一个figwheel已经准备好了,它会启动一个REPL,你可以在你的电脑中打开地址http://0.0.0.0:3000/来查看页面。
我正在发出 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:
如何将此值分配给 let
或 def
?
另外,为什么第二个console.log打印null
?
更新
我现在从使用 reagent
个原子转向 reframe
。
这是我的组件,成功 GET
s 数据,更新重新帧 '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-response
的atom
中。这里的关键是原子将暂时不包含任何内容(当请求完成时),然后响应将在其中,试剂将负责检测更改并重新渲染。最后,
quote-page
调用render-quote
生成标记以在加载时呈现报价或占位符。
为了 运行 整个事情,打开一个终端和 运行 lein run
这将启动默认侦听端口 3000 的 Web 服务器。在另一个终端中,运行 lein figwheel
将为您编译 ClojureScript 代码。一个figwheel已经准备好了,它会启动一个REPL,你可以在你的电脑中打开地址http://0.0.0.0:3000/来查看页面。