수색…


기본 채널 작업 : 생성, 퍼팅, 종료, 닫기 및 버퍼.

core.async 는 값을 가져 와서 채널 에 값을 넣는 프로세스 를 만드는 것에 관한 것입니다.

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

chan 채널 만들기

chan 함수를 사용하여 채널을 만듭니다.

(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

>!! 로 채널에 값 넣기 >!!>!

>!! 값을 사용하여 값을 채널에 넣을 수 있습니다 >!! :

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

nil 제외한 모든 값 (문자열, 숫자,지도, 컬렉션, 객체, 다른 채널 등)을 채널에 넣을 수 있습니다.

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

채널의 버퍼에 따라 >!! 현재 스레드를 차단할 수 있습니다.

(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.
  )

안쪽에서 (go ...) 블록을 사용 a/>! 사용할 수 있습니다 a/>! a/>!! 대신에 a/>!! :

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

논리적 동작은 a/>!! 와 같습니다 a/>!! , 실제 OS 스레드 대신에 goroutine의 논리적 프로세스 만 차단할 것입니다.

a/>!! 내부 (go ...) 블록은 anti-pattern입니다.

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

<!! 하여 채널에서 가치를 얻습니다 <!!

<!! 사용하여 채널에서 가치를 <!! :

;; 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

채널에서 사용할 수있는 항목이 없으면 a/<!! 값이 채널에 저장 될 때까지 (또는 채널이 닫힐 때까지), 현재 스레드를 차단합니다.

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

안쪽에서 (go ...) 블록을 사용 a/<! a/<!! 대신 a/<!! :

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

논리적 동작은 a/<!! 와 같습니다 a/<!! , 실제 OS 스레드 대신에 goroutine의 논리적 프로세스 만 차단할 것입니다.

a/<!! 사용 a/<!! 내부 (go ...) 블록은 anti-pattern입니다.

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

채널 닫기

a/close! close를 사용 하여 채널을 a/close! :

(a/close! ch)

채널이 닫히고 채널의 모든 데이터가 모두 소모되면 테이크는 항상 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

비동기 put!

a/>!! 대한 대안으로 a/>!! (차단할 수 있음), a/put! 부를 수 있습니다 a/put! 선택적 콜백을 사용하여 다른 스레드의 채널에 값을 넣을 수 있습니다.

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

ClojureScript에서는 현재 스레드를 차단할 수 없으므로 a/>!! 지원되지 않는다 put! (go) 블록 외부에서 채널에 데이터를 입력하는 유일한 방법입니다.

비동기가 걸립니다 take!

a/<!! (현재 스레드를 차단할 수 있음), a/take! 사용할 수 a/take! 비동기 적으로 채널에서 값을 가져 와서 콜백으로 전달합니다.

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

드롭 및 슬라이딩 버퍼 사용

드롭 및 슬라이딩 버퍼를 사용하면 put은 결코 차단되지 않지만 버퍼가 가득 차면 데이터가 손실됩니다. 슬라이딩 버퍼가 추가 된 첫 번째 데이터를 잃어 버리는 반면 버퍼를 삭제하면 마지막 데이터가 손실됩니다.

드롭 버퍼 예제 :

(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

슬라이딩 버퍼 예제 :

(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
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow