Lua在子过程后返回输出

问题描述

在lua工作时,我有一个键/值对表

1: "H < 12"
2: "(m > 30 ? foo : bar)"
3: ": baz"

长度可以是1个或多个。我需要遍历每个条目并运行一个子进程(通过一些libuv C绑定)。

对于普通的for循环,子过程是在循环完成运行后从libuv返回的结果,导致事物显示混乱。结果将是

  • 循环启动
  • 循环条目1
  • 工作1开始
  • 循环输入2
  • 工作2开始
  • 循环结束
  • Job1返回
  • Job2返回

我需要拥有的是

  • 循环启动
  • 循环条目1
  • 工作1开始
  • Job1返回
  • 循环输入2
  • 工作2开始
  • Job2返回
  • 循环结束

我还尝试过将自己的local fmtsToRun = { name = function() return configSubTable end } 版本写入并使用协程(协程)来处理回调

pairs()

这将导致此错误消息。


for fmt,output in jobIterator(fmtsToRun) do
  print('finished running',output)
end


  local function jobIterator(tbl)
    return coroutine.wrap(function()
      local fmtConf,fmtName
      fmtName,fmtConf = next(tbl,fmtName)
      if nil~=fmtConf then
          local conf = fmtConf()
          local output = nil
          -- wrapper util from Libuv library
          local job = Job:new({
              cmd = conf.cmd,args = conf.args,on_stdout = onStdout,-- process output
              on_stderr = onStderr,-- process any error
              on_exit = function()
                coroutine.yield(fmtName,output)
              end
          })
          job.send(conf.data)
      end
    end)
  end

等待attempt to yield across C-call boundary 完成并继续执行循环,同时保持正确顺序的“正确”方法是什么?

解决方法

一个更好的选择是手动控制流并递归地调用一个函数以一次遍历表的一个条目。

local runner = {}
for _,output in pairs(fmtsToRun) do
  table.insert(runner,output)
end
jobIterator(runner)

local function jobIterator(tbl)
  local F = {}
  function F.step()
    if #tbl == 0 then
      return
    end
    local current = table.remove(tbl,1)
    F.run(current)
  end
  
  function F.run(conf)
    local output = nil
    -- wrapper util from Libuv library
    local job =
      Job:new(
      {
        cmd = conf.cmd,args = conf.args,on_stdout = onStdout,-- process output
        on_stderr = onStderr,-- process any error
        on_exit = function()
          -- do what you need with output
          print(output)
          F.step()
        end
      }
    )
    job.send(conf.data)
  end

  F.step()
end