clojure - 使用 core.async 延迟显示 http 请求微调器的惯用方法
问题描述
我正在使用 ClojureScript+Rum 构建一个简单的 Web 应用程序,在多个地方我需要使用通过 http/get 请求从服务器获取的数据来显示 UI 片段。
通常我想在数据完全加载之前显示一个微调器。但我不想立即显示它,因为它可能会感觉闪烁(服务器可以足够快地返回响应),所以理想情况下它应该显示一些延迟(比如 300 毫秒)。因此,如果浏览器获得更快的响应,则微调器将不会显示。
如何以理想的 core.async 方式做到这一点?(见下面我的尝试)。
在 http 请求开始时立即开始显示微调器是微不足道的:
(ns my.app
(:require
;; -- snip --
[cljs-http.client :as http]
[cljs.core.async :as ca]))
(defonce *state (atom {:loading false :data nil}))
(defn get-data! []
(go
(swap! *state assoc :loading true)
(let [response (<! (http/get "/api/data"))
data (:body response)]
(swap! *state assoc :loading false :data data))))
;; -- render the data or spinner if :loading --
但是如何延迟显示微调器?我尝试通过将“混合”“超时”和“响应”通道“混合”在一起,然后检查我从结果通道获得的值。它可以工作,但代码感觉很笨拙:
(defonce *state (atom {:loading false :data nil}))
(defn timeout-return [out ms val]
(go
(<! (ca/timeout ms))
(ca/put! out val)))
(defn http-get [out uri]
(go
(let [response (<! (http/get uri))]
(ca/put! out response)
)))
(defn get-data! []
(go
(let [t-out (ca/chan)
resp-out (ca/chan)
out (ca/chan)
mix-out (ca/mix out)
handle-timeout (fn [] (swap! *state assoc :loading true))
handle-resp (fn [r] (swap! *state assoc :loading false :data (:body r)))]
(ca/admix mix-out t-out)
(ca/admix mix-out resp-out)
(timeout-return t-out 400 :timeout)
(http-get resp-out "/api/data")
(let [r (<! out)]
(if (= :timeout r)
(do
(handle-timeout)
(handle-resp (<! out)))
(handle-resp r)))
)))
;; -- render the data or spinner if :loading --
有一个更好的方法吗?
解决方案
就我个人而言,我会避免使用 core.async ,除非您的并发性足够复杂以至于承诺不够。标准 js 承诺不需要担心的创建和拉取通道的开销很大。
为了延迟微调器,我会使用去抖动。也许这会有所帮助:https ://www.martinklepsch.org/posts/simple-debouncing-in-clojurescript.html
否则你可以谷歌如何实现去抖动。
基本上你想这样做:
- 为您的请求创建一个承诺
- 启动去抖动任务:修改状态以指示加载
- 在承诺上
.finally
,取消任何活动的去抖动任务并修改状态以表明您不再加载
推荐阅读
- java - Persisting and removing an entity in the same transaction
- powerbi - Difference between values of different categories in Power BI matrix
- r - 如何在 R tibble 中的至少一半元素中找到共同的元素
- floating-point - 如果两个整数的乘积在浮点类型的无损范围内,是否会无损?
- windows - Windows 10 旁加载 - 我可以限制哪些应用程序可以通过证书旁加载?
- c# - 为什么我的 .NET 框架应用程序在寻找 .NET 核心/标准平台扩展程序集的错误版本,我该如何解决?
- python - 子进程不执行 Rscript
- r - R:将四个变量合二为一
- r - 将数字因素集中在一起
- eclipse - Eclipse 设置中的行尾字符触发器