提问人:Luli 提问时间:4/13/2022 最后编辑:Luli 更新时间:4/14/2022 访问量:217
Lua - 通过 HTTP 异步下载文件
Lua - Download file asynchronously via HTTP
问:
我刚刚读完了核心代码。我想编写代码从网站异步下载文件,但 copas 似乎只支持套接字 IO。copas
由于 Lua 不提供异步语法,并且其他包肯定会有自己的事件循环,我认为这些循环不能沿着 copas 的循环运行。
那么要通过 http 异步下载文件,我是否必须找到一个同时支持异步 http 和异步文件 IO 的包?还是其他想法?
答:
0赞
Luli
4/14/2022
#1
在阅读了一堆代码之后,我终于可以回答我自己的问题了。
正如我在对这个问题的评论中提到的,可以利用异步 IO 库导出的 step 函数,并将多个步进合并到一个更大的循环中。
在 的情况下,它使用 C 语言中的外部线程池来管理文件 IO,并使用单线程循环来调用挂起的回调并管理 IO 轮询(在我的用例中不需要轮询)。luv
可以简单地调用 提供的文件操作函数来制作异步文件 IO。但仍然需要 step 的循环来调用回调绑定到 IO 操作。luv
luv
整数主循环如下所示:
local function main_loop()
copas.running = true
while not copas.finished() or uv.loop_alive() do
if not copas.finished() then
copas.step()
end
if uv.loop_alive() then
uv.run("nowait")
end
end
end
copas.step()
是 的步进函数。并且只运行一次事件循环,并且在轮询时没有准备好的 IO 时不要阻塞。copas
uv.run("nowait")
luv
一个有效的解决方案如下所示:
local copas = require "copas"
local http = require "copas.http"
local uv = require "luv"
local urls = {
"http://example.com",
"http://example.com"
}
local function main_loop()
copas.running = true
while not copas.finished() or uv.loop_alive() do
if not copas.finished() then
copas.step()
end
if uv.loop_alive() then
uv.run("nowait")
end
end
end
local function write_file(file_path, data)
-- ** call to luv async file IO **
uv.fs_open(file_path, "w+", 438, function(err, fd)
assert(not err, err)
uv.fs_write(fd, data, nil, function(err_o, _)
assert(not err_o, err_o)
uv.fs_close(fd, function(err_c)
assert(not err_c, err_c)
print("finished:", file_path)
end)
end)
end)
end
local function dl_url(url)
local content, _, _, _ = http.request(url)
write_file("foo.txt", content)
end
-- adding task to copas' loop
for _, url in ipairs(urls) do
copas.addthread(dl_url, url)
end
main_loop()
评论
step
step