You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lua中是否存在类似JS、Python的多协程等待完成等效实现?

Lua中实现类似Promise.all/asyncio.gather的多协程等待功能

在JavaScript中,我们可以通过Promise.all等待多个异步任务完成并获取结果:

const [a, b] = await Promise.all([task1(), task2()])

在Python中,对应的实现是asyncio.gather:

a, b = await asyncio.gather(task1(), task2())

Lua中的实现方案

Lua标准库并没有内置类似coroutine.resume_all的方法,需要我们手动实现多协程等待的逻辑。以下是两种常见的实现方式:

1. 等待所有协程完成(收集所有结果/错误)

这个实现会等待所有协程执行完毕,无论是否出现错误,最后统一返回结果或错误信息:

function gather(...)
    local coros = {...}
    local results = {}
    local errors = {}
    local alive_count = #coros

    -- 初始化启动所有协程
    for idx, co in ipairs(coros) do
        local ok, val = coroutine.resume(co)
        if not ok then
            errors[idx] = val
            alive_count = alive_count - 1
        else
            if coroutine.status(co) == 'dead' then
                results[idx] = val
                alive_count = alive_count - 1
            else
                results[idx] = {co = co, last_val = val}
            end
        end
    end

    -- 轮询直到所有协程结束
    while alive_count > 0 do
        for idx, data in ipairs(results) do
            if type(data) == 'table' then
                local ok, val = coroutine.resume(data.co, data.last_val)
                if not ok then
                    errors[idx] = val
                    results[idx] = nil
                    alive_count = alive_count - 1
                else
                    if coroutine.status(data.co) == 'dead' then
                        results[idx] = val
                        alive_count = alive_count - 1
                    else
                        data.last_val = val
                    end
                end
            end
        end
    end

    -- 返回结果或错误
    if next(errors) then
        return false, errors
    else
        return true, table.unpack(results)
    end
end

使用示例:

-- 模拟任务1:分步执行后返回结果
local function task1()
    for i = 1, 3 do
        coroutine.yield("task1 step " .. i)
    end
    return "task1 completed"
end

-- 模拟任务2:执行中抛出错误
local function task2()
    coroutine.yield("task2 step 1")
    error("task2 encountered an error")
end

local co1 = coroutine.create(task1)
local co2 = coroutine.create(task2)

local ok, res_or_err = gather(co1, co2)
if not ok then
    print("执行错误:")
    for idx, err in pairs(res_or_err) do
        print(string.format("任务%d:%s", idx, err))
    end
else
    print("执行结果:", res_or_err)
end

2. 快速失败模式(任一协程报错立即终止)

这个实现类似Promise.all的行为:只要有一个协程执行报错,就立即停止所有等待并返回错误:

function gather_fast_fail(...)
    local coros = {...}
    local results = {}
    local alive_count = #coros

    while alive_count > 0 do
        local err_info = nil
        for idx, co in ipairs(coros) do
            if coroutine.status(co) ~= 'dead' then
                local ok, val = coroutine.resume(co)
                if not ok then
                    err_info = {task_idx = idx, msg = val}
                    break
                end
                if coroutine.status(co) == 'dead' then
                    results[idx] = val
                    alive_count = alive_count - 1
                end
            end
        end
        if err_info then
            return false, string.format("任务%d报错:%s", err_info.task_idx, err_info.msg)
        end
    end
    return true, table.unpack(results)
end

使用这个函数时,只要任一任务报错,就会直接返回错误信息,不会等待其他任务完成。

内容的提问来源于stack exchange,提问作者Nil Admirari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 03:52:43