2015-09-14 16 views
6

Esiste un modo elegante per bloccare un blocco di ricerca?Come interrompere il blocco go in ClojureScript/core.async?

(senza introdurre una bandiera e inquinare il codice con controlli/filiali)

(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) 
+0

'(chiudi! Attività)' forse? - primo risultato su google. – birdspider

risposta

4

spiace, ma questo non è possibile con oggi core.async. Quello che si ottiene dalla creazione di un blocco go è un canale normale su quale sarà il risultato del blocco, anche se questo non fornisce alcun handle al blocco stesso.

2

Come indicato nella risposta di Arthur, non si può interrompere un blocco go subito, ma dal momento che il vostro esempio indica un compito in più fasi (con sotto-attività), un approccio come questo potrebbe funzionare :

(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)) 
Problemi correlati