LuaCoroutine&Promise

1,187 阅读3分钟

LuaCoroutine

Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。

适用场景:

  • 网络请求
  • IO操作

一个栗子

-- 创建一个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种状态

  • dead结束
  • suspend挂起
  • running 执行中

6个方法:

  • create

创建coroutine,返回coroutine, 参数是一个函数,当和resume配合使用的时候就唤醒函数调用

  • resume

重启coroutine,和create配合使用

  • yield

挂起coroutine,将coroutine设置为挂起状态,这个和resume配合使用能有很多有用的效果

  • status

查看coroutine的状态 注:coroutine的状态有三种:dead,suspend,running,具体什么时候有这样的状态请参考下面的程序

  • wrap

创建coroutine,返回一个函数,一旦你调用这个函数,就进入coroutine,和create功能重复

  • running

返回正在跑的coroutine,一个coroutine就是一个线程,当使用running的时候,就是返回一个corouting的线程号

更多的栗子

-- 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最大的好处是在异步执行的流程中,把执行代码和处理结果的代码清晰地分离了

Promise还可以做更多的事情,比如,有若干个异步任务,需要先做任务1,如果成功后再做任务2,任何任务失败则不再继续并执行错误处理函数。

要串行执行这样的异步任务,不用Promise需要写一层一层的嵌套代码。有了Promise,我们只需要简单地写:

job1.then(job2).then(job3).catch(handleError);

LuaPromise

通过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