问题描述
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