Zoeken…


basiskanaalbewerkingen: creëren, plaatsen, nemen, sluiten en buffers.

core.async gaat over het maken van processen die waarden core.async aan en waarden in kanalen zetten .

(require [clojure.core.async :as a])

Kanalen maken met chan

Je maakt een kanaal met de chan functie:

(def chan-0 (a/chan)) ;; unbuffered channel: acts as a rendez-vous point.
(def chan-1 (a/chan 3)) ;; channel with a buffer of size 3. 
(def chan-2 (a/chan (a/dropping-buffer 3)) ;; channel with a *dropping* buffer of size 3
(def chan-3 (a/chan (a/sliding-buffer 3)) ;; channel with a *sliding* buffer of size 3

Waarden in kanalen zetten met >!! en >!

Je zet waarden in een kanaal met >!! :

(a/>!! my-channel :an-item)

U kunt elke waarde (tekenreeksen, getallen, kaarten, collecties, objecten, zelfs andere kanalen, enz.) In een kanaal plaatsen, behalve nil :

;; WON'T WORK
(a/>!! my-channel nil)
=> IllegalArgumentException Can't put nil on channel

Afhankelijk van de buffer van het kanaal, >!! kan de huidige thread blokkeren.

(let [ch (a/chan)] ;; unbuffered channel
  (a/>!! ch :item) 
  ;; the above call blocks, until another process 
  ;; takes the item from the channel.
  )
(let [ch (a/chan 3)] ;; channel with 3-size buffer
  (a/>!! ch :item-1) ;; => true
  (a/>!! ch :item-2) ;; => true
  (a/>!! ch :item-3) ;; => true
  (a/>!! ch :item-4) 
  ;; now the buffer is full; blocks until :item-1 is taken from ch.
  )

Vanuit een (go ...) blok kun je - en moet - a/>! in plaats van a/>!! :

 (a/go (a/>! ch :item))

Het logische gedrag is hetzelfde als a/>!! , maar alleen het logische proces van de goroutine wordt geblokkeerd in plaats van de daadwerkelijke OS-thread.

a/>!! binnen een (go ...) blok zit een anti-patroon:

;; NEVER DO THIS
(a/go 
  (a/>!! ch :item))

Waarden nemen van kanalen met <!!

Je neemt een waarde van een kanaal met <!! :

;; creating a channel
(def ch (a/chan 3))
;; putting some items in it
(do 
  (a/>!! ch :item-1)
  (a/>!! ch :item-2)
  (a/>!! ch :item-3))
;; taking a value
(a/<!! ch) ;; => :item-1
(a/<!! ch) ;; => :item-2

Als er geen item beschikbaar is in het kanaal, a/<!! blokkeert de huidige thread totdat een waarde in het kanaal wordt geplaatst (of het kanaal wordt gesloten, zie later):

(def ch (a/chan))
(a/<!! ch) ;; blocks until another process puts something into ch or closes it

Vanuit een (go ...) blok kun je - en moet - a/<! in plaats van a/<!! :

 (a/go (let [x (a/<! ch)] ...))

Het logische gedrag is hetzelfde als a/<!! , maar alleen het logische proces van de goroutine wordt geblokkeerd in plaats van de daadwerkelijke OS-thread.

Gebruik van a/<!! binnen een (go ...) blok zit een anti-patroon:

;; NEVER DO THIS
(a/go 
  (a/<!! ch))

Kanalen sluiten

Je sluit een kanaal met a/close! :

(a/close! ch)

Zodra een kanaal is gesloten en alle gegevens in het kanaal zijn uitgeput, retourneert takes altijd nil :

(def ch (a/chan 5))

;; putting 2 values in the channel, then closing it
(a/>!! ch :item-1)
(a/>!! ch :item-2)
(a/close! ch)

;; taking from ch will return the items that were put in it, then nil
(a/<!! ch) ;; => :item-1
(a/<!! ch) ;; => :item-2
(a/<!! ch) ;; => nil
(a/<!! ch) ;; => nil
(a/<!! ch) ;; => nil

;; once the channel is closed, >!! will have no effect on the channel:
(a/>!! ch :item-3)
=> false ;; false means the put did not succeed
(a/<!! ch) ;; => nil

Asynchrone zet met put!

Als alternatief voor a/>!! (die kan blokkeren), kunt u a/put! bellen a/put! om een waarde in een kanaal in een andere thread te plaatsen, met een optionele callback.

(a/put! ch :item)
(a/put! ch :item (fn once-put [closed?] ...)) ;; callback function, will receive 

In ClojureScript is het blokkeren van de huidige thread niet mogelijk, a/>!! wordt niet ondersteund en put! is de enige manier om gegevens in een kanaal te plaatsen van buiten een (go) blok.

Asynchrone neemt met take!

Als alternatief voor a/<!! (waardoor de huidige thread kan worden geblokkeerd), kunt u a/take! om een waarde asynchroon van een kanaal te nemen en door te geven aan een callback.

(a/take! ch (fn [x] (do something with x)))

Dropping en sliding buffers gebruiken

Met laten vallen en glijden buffers, zet nooit blokkeren, echter, wanneer de buffer vol is, verlies je gegevens. Droppingbuffer verliest de laatst toegevoegde gegevens, terwijl glijdende buffers de eerste toegevoegde gegevens verliezen.

Dropping buffer voorbeeld:

(def ch (a/chan (a/dropping-buffer 2)))

;; putting more items than buffer size
(a/>!! ch :item-1)
=> true ;; put succeeded
(a/>!! ch :item-2)
=> true
(a/>!! ch :item-3)
=> false ;; put failed

;; no we take from the channel
(a/<!! ch)
=> :item-1
(a/<!! ch)
=> :item-2
(a/<!! ch)
;; blocks! :item-3 is lost

Voorbeeld van glijdende buffer:

(def ch (a/chan (a/sliding-buffer 2)))

;; putting more items than buffer size
(a/>!! ch :item-1)
=> true
(a/>!! ch :item-2)
=> true
(a/>!! ch :item-3)
=> true

;; no when we take from the channel:
(a/<!! ch)
=> :item-2
(a/<!! ch)
=> :item-3
;; :item-1 was lost


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow