Lua 協同程序(coroutine)與線程比較相似:擁有獨立的堆棧,獨立的局部變量,獨立的指令指針,同時又與其它協同程序共享全局變量和其它大部分東西。html
適用場景:git
-- 建立一個coroutine
co = coroutine.create(function ()
print("hello coroutine")
end)
print(co) -- thread: 0x00021d68
print(coroutine.status(co)) -- suspended 未被執行或者執行中提示掛起suspended
coroutine.resume(co) -- hello coroutine 執行
print(coroutine.status(co)) -- dead 執行以後變爲dead狀態
複製代碼
Coroutine一共有3種狀態github
6個方法:promise
建立coroutine,返回coroutine, 參數是一個函數,當和resume配合使用的時候就喚醒函數調用bash
重啓coroutine,和create配合使用網絡
掛起coroutine,將coroutine設置爲掛起狀態,這個和resume配合使用能有不少有用的效果異步
查看coroutine的狀態 注:coroutine的狀態有三種:dead,suspend,running,具體何時有這樣的狀態請參考下面的程序函數
建立coroutine,返回一個函數,一旦你調用這個函數,就進入coroutine,和create功能重複ui
返回正在跑的coroutine,一個coroutine就是一個線程,當使用running的時候,就是返回一個corouting的線程號lua
-- Yield栗子
co_func = function() -- 聲明一個支持yield的函數
for i = 1,3 do
print("co",i)
coroutine.yield() -- 設爲掛起狀態
end
print("函數結束")
end
co = coroutine.create(co_func)
coroutine.resume(co) -- 1
coroutine.resume(co) -- 2
print(coroutine.status(co)) -- suspended 執行中爲掛起狀態
coroutine.resume(co) -- 3
coroutine.resume(co) -- "函數結束"
print(coroutine.status(co)) -- dead 整個函數執行完畢
print(coroutine.resume(co)) -- false cannot resume dead coroutine 結束的coroutine再被執行會報這個錯誤
複製代碼
-- coroutine return的栗子
co = coroutine.create(function(a,b,c)
print("co",a,b,c)
end)
coroutine.resume(co,1,2,3) -- 多餘的參數會傳遞給coroutine中main函數中
co = coroutine.create(function (a,b)
coroutine.yield(a+b,a-b)
end)
print(coroutine.resume(co,20,10)) -- yield除了返回true以外,還會返回參數
co = coroutine.create(function()
print(coroutine.yield())
end)
coroutine.resume(co) -- 由於第一次執行 print執行一半被yield掛起了
coroutine.resume(co,4,5) -- 因此第二次執行纔會執行完整的print
co = coroutine.create(function()
return 6,7
end)
print(coroutine.resume(co)) -- 當coroutine執行完畢後 return中的參數會返回給resume
複製代碼
-- 生產消費者的栗子
local newProductor
function productor()
local i = 0
while true do
i = i + 1
send(i) -- 將生產的物品發送給消費者
end
end
function consumer()
while true do
local i = receive() -- 從生產者那裏獲得物品
print(i)
end
end
function receive()
local status, value = coroutine.resume(newProductor)
return value
end
function send(x)
coroutine.yield(x) -- x表示須要發送的值,值返回之後,就掛起該協同程序
end
-- 啓動程序
newProductor = coroutine.create(productor)
consumer()
複製代碼
Promise最大的好處是在異步執行的流程中,把執行代碼和處理結果的代碼清晰地分離了
Promise還能夠作更多的事情,好比,有若干個異步任務,須要先作任務1,若是成功後再作任務2,任何任務失敗則再也不繼續並執行錯誤處理函數。
要串行執行這樣的異步任務,不用Promise須要寫一層一層的嵌套代碼。有了Promise,咱們只須要簡單地寫:
job1.then(job2).then(job3).catch(handleError);
複製代碼
經過Coroutine能夠很方便的實現相似JS裏Promise的操做
經過使用deferred這個輪子就開發流式的網絡請求了(輪子源碼在文章最後貼出)
deferred = require('./Coroutine/deferred')
function httpGet() -- 模擬網絡請求
local d = deferred.new()
local success = true
if success then
d:resolve( "success")
else
d:reject("error")
end
return d
end
-- promise用法
httpGet():next(function(result)
print(result)
return result.."option1" -- return數據到下一步
end):next(function(result)
print(result)
end,function(error) -- 只要前面有return reject 就會走最後的error
print(error)
end)
複製代碼
菜鳥LuaCoroutine教程: http://www.runoob.com/lua/lua-coroutine.html
輪子: https://github.com/zserge/lua-promises