国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

js-csp 異步編程的一些簡單的例子

curried / 2579人閱讀

摘要:發(fā)現一個月沒刷技術文章了有點慌整理一篇短的用法出來只包含最基本的用法在里邊最清晰不過我是在寫的版本的實現包含異步用法會更繁瑣一些但是也值得看看我相信普及之前還是一個很有意思的選擇我的代碼寫的是可以自動腦補圓括號花括號上去注意包含的函數自動

發(fā)現一個月沒刷技術文章了, 有點慌, 整理一篇短的 CSP 用法出來,
只包含最基本的用法, 在 Go 里邊最清晰, 不過我是在 Clojure 寫的 CSP.
js 版本的 CSP 實現包含異步, 用法會更繁瑣一些, 但是也值得看看.
我相信 async/await 普及之前, js-csp 還是一個很有意思的選擇.

我的代碼寫的是 CoffeeScript, 可以自動腦補圓括號花括號上去...
注意包含 yield 的函數自動被轉成 function*() {}, 所以注意腦補.
腦補不出來的只好貼在這邊編譯下了 http://coffeescript.org/

使用 timeout

首先是最基本的 CSP 的例子, 也就是用同步的代碼寫異步的邏輯,
CSP 當中最核心的概念是 Channel, 最簡單的 csp.timeout(1000) 創(chuàng)建 channel.

csp = require "js-csp"

# 用 csp.go 啟動一個 yield 函數
csp.go ->
  # 有 csp.take 從這個管道取出數據, yield 來模擬阻塞的效果
  yield csp.take csp.timeout(1000)
  console.log "Gone 1s"

運行一下:

=>> coffee async.coffee
Gone 1s

我注意到對于 timeout 來說, 省掉 csp.take 也是能夠正常運行的:

csp = require "js-csp"

csp.go -> # 腦補 yield 函數

  yield csp.timeout 1000
  console.log "Gone 1s"
  yield csp.timeout 2000
  console.log "Gone 2s"
  yield csp.timeout 3000
  console.log "Gone 3s. End"

運行一下:

=>> coffee async.coffee
Gone 1s
Gone 2s
Gone 3s. End
使用 put 和 take

csp.timeout 比較特殊, 默認就會產生數據, 只要進行 csp.take 就好了.
一般的 Channel 的話, 需要手動創(chuàng)建出來, 然后手動推數據,
比如下面的代碼創(chuàng)建了一個數據, 用 csp.go 啟動另一個"進程"往 Channel 推數據,
這里的"進程"的說法并不是真正的進程, 只是模擬進程的行為:

csp = require "js-csp"

talk = (ch) ->
  yield csp.timeout 3000
  console.log "Done 3s timeout"
  # 等待 3s 然后往 Channel 當中寫入數據, yield 會產生等待
  yield csp.put ch, "some result"

csp.go ->
  ch = csp.chan()

  # 啟動另一個"進程"
  csp.go talk, [ch] # 數組里是傳給 talk 函數的參數

  # 使用 yield.take 從 Channel 取出數據, 使用 yield 模擬等待
  result = yield csp.take ch
  console.log "Result:", JSON.stringify(result)

運行一下:

=>> coffee async.coffee
Done 3s timeout
Result: "some result"
假裝有兩個進程

同樣是上邊的代碼, 只是調整一下寫法, 看上去像是分別啟動了兩個"進程",
雖然它們的運行時獨立的, 但是可以通過管道進行通信,
而且在對應的 csp.takecsp.put 操作過程中, 會通過 yield 進行等待:

csp = require "js-csp"

talk = (ch) ->
  yield csp.timeout 3000
  console.log "Done 3s timeout"
  yield csp.put ch, "some result"

listen = (ch) ->
  result = yield csp.take ch
  console.log "Result:", JSON.stringify(result)

# 創(chuàng)建 Channel, 啟動兩個"進程"
theCh = csp.chan()
# csp.go 后面第一個是 yield 函數, 第二個是參數的數組, 雖然比較難看
csp.go talk, [theCh]
csp.go listen, [theCh]

運行一下:

=>> coffee async.coffee
Done 3s timeout
Result: "some result"
封裝異步事件

實際使用當中, 會需要把 js 環(huán)境的異步代碼封裝成管道的形式,
不封裝成管道, 就不能借助 csp.go 來封裝同步代碼了,
由于 js 不像 Go 那樣整個語言層面做了處理, 實際上會有奇怪的寫法,
所以 js-csp 提供了 csp.putAsynccsp.takeAsync:

csp = require "js-csp"

talk = (ch) ->
  setTimeout ->
    csp.putAsync ch, "some result"
    console.log "Finished 3s of async"
  , 3000

listen = (ch) ->
  result = yield csp.take ch
  console.log "Result:", JSON.stringify(result)

theCh = csp.chan()
talk theCh
csp.go listen, [theCh]

運行一下:

=>> coffee async.coffee
Finished 3s of async
Result: "some result"
處理超時

一個操作是否超時的問題, 可以同時啟動一個定時的"進程",
然后觀察兩個"進程"哪一個先執(zhí)行完成, 從而判斷是否超時,
這就用到了 csp.alts 函數, 這個奇怪的命名是用 Clojure 帶過來的:

csp = require "js-csp"

talk = (ch) ->
  time = Math.random() * 4 * 1000
  setTimeout ->
    console.log "Get result after #{time}ms"
    csp.putAsync ch, "some result"
  , time

listen = (ch) ->
  hurry = csp.timeout 2000
  # 通過 csp.alts 同時等待多個 Channel 返回數據
  result = yield csp.alts [ch, hurry]
  # result.channel 可以用于判斷數據的來源, result.value 才是真正的數據
  if result.channel is hurry
    console.log "Too slow, got no result"
    # close 只是設置 Channel 的狀態(tài), 其實還需要手工處理一些邏輯
    hurry.close()
  else
    console.log "Fast enough, got", JSON.stringify(result.value)

theCh = csp.chan()
talk theCh
csp.go listen, [theCh]

用了隨機數, 運行多次試一下, 可以看到根據不同的時間, 結果是不一樣的:

=>> coffee async.coffee
Too slow, got no result
Get result after 3503.6168682995008ms

=>> coffee async.coffee
Too slow, got no result
Get result after 3095.264637685924ms

=>> coffee async.coffee
Get result after 703.6501633183257ms
Fast enough, got "some result"

=>> coffee async.coffee
Too slow, got no result
Get result after 3729.5125755664317ms

=>> coffee async.coffee
Get result after 101.51519531067788ms
Fast enough, got "some result"
循環(huán)任務

yield 用法類似, 如果有循環(huán)的代碼, 也可以用 CSP 寫出來,
這個的話不用怎么想應該能明白了, loop 只是 while true 的語法糖:

csp = require "js-csp"

chatter = (ch) ->
  counter = 0
  loop
    yield csp.timeout 1000
    counter += 1
    yield csp.put ch, counter

repeat = (ch) ->
  loop
    something = yield csp.take ch
    console.log "Hear something:", something

theCh = csp.chan()
csp.go chatter, [theCh]
csp.go repeat, [theCh]

運行一下:

=>> coffee async.coffee
Hear something: 1
Hear something: 2
Hear something: 3
Hear something: 4
^C
多個數據的消費者

實際場景當中會遇到多個消費者從單個生產者讀取數據的需求,
這是一個用 Channel 比較合適的場景, 啟動兩個"進程"讀取一個 Channel 就好了,
下面我模擬的是不同的處理時間 300ms 和 800ms 讀取 100ms 頻率的數據,
因為 CSP 自動處理了等待, 整個代碼看上去挺簡單的:

csp = require "js-csp"

chatter = (ch) ->
  counter = 0
  loop
    yield csp.timeout 100
    counter += 1
    yield csp.put ch, counter

repeat = (ch) ->
  loop
    yield csp.timeout 800
    something = yield csp.take ch
    console.log "Hear at 1:", something

repeat2 = (ch) ->
  loop
    yield csp.timeout 300
    something = yield csp.take ch
    console.log "Hear at 2:", something

theCh = csp.chan()
csp.go chatter, [theCh]
csp.go repeat, [theCh]
csp.go repeat2, [theCh]

運行一下:

=>> coffee async.coffee
Hear at 2: 1
Hear at 2: 2
Hear at 1: 3
Hear at 2: 4
Hear at 2: 5
Hear at 2: 6
Hear at 1: 7
Hear at 2: 8
Hear at 2: 9
Hear at 1: 10
Hear at 2: 11
Hear at 2: 12
Hear at 2: 13
Hear at 1: 14
Hear at 2: 15
Hear at 2: 16
Hear at 1: 17
Hear at 2: 18
Hear at 2: 19
Hear at 2: 20
Hear at 1: 21
Hear at 2: 22
Hear at 2: 23
Hear at 1: 24
^C
使用 buffer

默認情況下管道是阻塞的, csp.put csp.take 成對進行,
也就是說, 只有一個就緒的話, 它會等待另一個開始, 然后一起執(zhí)行,
但是用 buffer 的話, 管道就會先在一定范圍內進行緩存,
這樣 csp.put 就可以先運行下去了, 這個是不難理解的...
管道實際上有 3 種策略, fixed, dropping, sliding:

fixed, 緩存放滿以后就會開始形成阻塞了

dropping, 緩存滿了以后, 新的數據就會丟棄

sliding, 緩存滿以后, 會丟棄掉舊的數據讓新數據能放進緩存

隨便演示一個丟棄數據的例子:

csp = require "js-csp"

chatter = (ch) ->
  counter = 0
  loop
    yield csp.timeout 200
    counter += 1
    console.log "Write data:", counter
    yield csp.put ch, counter

repeat = (ch) ->
  loop
    yield csp.timeout 300
    something = yield csp.take ch
    console.log "Hear:", something

theCh = csp.chan(csp.buffers.dropping(3))
csp.go chatter, [theCh]
csp.go repeat, [theCh]

運行一下, 可以看到 "Hear" 部分丟失了一些數據, 但前三個數據不會丟:

=>> coffee async.coffee
Write data: 1
Hear: 1
Write data: 2
Hear: 2
Write data: 3
Write data: 4
Hear: 3
Write data: 5
Hear: 4
Write data: 6
Write data: 7
Hear: 5
Write data: 8
Hear: 6
Write data: 9
Write data: 10
Hear: 7
Write data: 11
Hear: 8
Write data: 12
Write data: 13
Hear: 9
Write data: 14
Hear: 11
Write data: 15
Write data: 16
Hear: 12
Write data: 17
Hear: 14
^C
小結

由于 CSP 是在 Go 語言發(fā)明的, 完整的用法還是看 Go 的教程比較好,
到了 Clojure 和 js 當中難免會增加一些坑, 特別是 js 當中...
上面提到的 API 在 js-csp 的文檔上有描述, 例子也有, 但是挺少的:

https://github.com/ubolonton/...

https://github.com/ubolonton/...

另外還有一些高級一點的用法, 比如數據的 transform 和 pipe 之類的,
其實就是 Stream 的用法在 Channel 上的改版, 某種程度上 Channel 也是 Stream,
對于我個人來說, Channel 的抽象比起 Stream 的抽象舒服多了.

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/86652.html

相關文章

  • js-csp 可以開始嘗試了

    摘要:的用例的用法最早是語言傳開來的看一下我從網上扒的代碼其中符號是往當中寫入數據的操作同時注意一般的位置對于來說是阻塞的由于能夠處理異步操作也就是說能做到異步代碼用同步寫法更多的細節(jié)搜索應該就能找到除了也實現了對于的支持也就是 CSP 的用例 CSP 的用法最早是 Go 語言傳開來的, 看一下我從網上扒的代碼: package main import fmt func ping(pin...

    tracymac7 評論0 收藏0
  • [譯] 快速介紹 JavaScript 中 CSP

    摘要:原文的個示例是什么一般來說它是寫并行代碼的一套方案在語言里自帶該功能通過基于的來實現現在通過也能做支持了或者說的功能為什么我要關心因為它強大啊而且高效而且簡單都這樣了你還想要什么好吧說細節(jié)怎樣使用呢我們用而且需要支持才有也就說或者更高的版 原文 http://lucasmreis.github.io/b... Communicating Sequential Processes 的 7...

    Rocko 評論0 收藏0
  • React 組件之間如何交流

    摘要:前言今天群里面有很多都在問關于組件之間是如何通信的問題,之前自己寫的時候也遇到過這類問題。英文能力有限,如果有不對的地方請跟我留言,一定修改原著序處理組件之間的交流方式,主要取決于組件之間的關系,然而這些關系的約定人就是你。 前言 今天群里面有很多都在問關于 React 組件之間是如何通信的問題,之前自己寫的時候也遇到過這類問題。下面是我看到的一篇不錯英文版的翻譯,看過我博客的人都知道...

    tomlingtm 評論0 收藏0
  • ES6 Generator實現協(xié)同程序

    摘要:關鍵字表示代碼在該處將會被阻塞式暫停阻塞的僅僅是函數代碼本身,而不是整個程序,但是這并沒有引起函數內部自頂向下代碼的絲毫改變。通過實現模式在通過實現理論的過程中已經有一些有趣的探索了。 至此本系列的四篇文章翻譯完結,查看完整系列請移步blogs 由于個人能力知識有限,翻譯過程中難免有紕漏和錯誤,望不吝指正issue ES6 Generators: 完整系列 The Basics...

    MudOnTire 評論0 收藏0
  • js 異步編程

    摘要:總結這篇文章簡單的介紹了一些常用的異步編程的方法,如果有錯誤或不嚴謹的地方,歡迎批評指正,如果喜歡,歡迎點贊收藏。 大家都知道js的執(zhí)行環(huán)境是單線程的,如果沒有異步編程,那么js的執(zhí)行效率會非常低下,導致程序十分卡頓,一提到異步編程大家首先的想到的一定是回調函數,這也是最常用的異步編程的形式,但其實常用的還有Promise和Async函數,接下來就讓我們一起學習這幾種常用的異步編程方法...

    diabloneo 評論0 收藏0

發(fā)表評論

0條評論

curried

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<