如何在ClojureScript / core.async中停止去块?

时间:2015-09-14 17:58:52

标签: clojure clojurescript core.async

是否有一种优雅的方法可以阻止跑步挡?

(不引入标志并用支票/分支污染代码)

(ns example
  (:require-macros [cljs.core.async.macros :refer [go]])
  (:require        [cljs.core.async        :refer [<! timeout]]))

(defn some-long-task []
  (go
    (println "entering")

    ; some complex long-running task (e.g. fetching something via network)
    (<! (timeout 1000)) 
    (<! (timeout 1000))
    (<! (timeout 1000))
    (<! (timeout 1000))

    (println "leaving")))

; run the task
(def task (some-long-task))

; later, realize we no longer need the result and want to cancel it 
; (stop! task)

3 个答案:

答案 0 :(得分:4)

抱歉,今天使用core.async是不可能的。从创建go块返回的内容是块的结果将被放置的正常通道,尽管这不会为您提供实际块本身的任何句柄。

答案 1 :(得分:3)

如Arthur的回答所述,您无法立即终止go阻止,但是由于您的示例表明了一个多阶段任务(使用子任务),这样的方法可能会起作用:

(defn task-processor
  "Takes an initial state value and number of tasks (fns). Puts tasks
  on a work queue channel and then executes them in a go-loop, with
  each task passed the current state. A task's return value is used as
  input for next task. When all tasks are processed or queue has been
  closed, places current result/state onto a result channel. To allow
  nil values, result is wrapped in a map:

  {:value state :complete? true/false}

  This fn returns a map of {:queue queue-chan :result result-chan}"
  [init & tasks]
  (assert (pos? (count tasks)))
  (let [queue  (chan)
        result (chan)]
    (async/onto-chan queue tasks)
    (go-loop [state init, i 0]
      (if-let [task (<! queue)]
        (recur (task state) (inc i))
        (do (prn "task queue finished/terminated")
            (>! result {:value state :complete? (== i (count tasks))}))))
    {:queue  queue
     :result result}))

(defn dummy-task [x] (prn :task x) (Thread/sleep 1000) (inc x))

;; kick of tasks
(def proc (apply task-processor 0 (repeat 100 dummy-task)))

;; result handler
(go
  (let [res (<! (:result proc))]
    (prn :final-result res)))

;; to stop the queue after current task is complete
;; in this example it might take up to an additional second
;; for the terminated result to be delivered
(close! (:queue proc))

答案 2 :(得分:1)

您可能希望使用future和future-cancel来完成此类任务。

(def f (future (while (not (Thread/interrupted)) (your-function ... ))))
(future-cancel f)

function pointer