我刚刚读完了copas的核心代码。我想写代码异步从网站下载文件,但是copas似乎只支持socket IO。
因为Lua不提供异步语法,而且其他包肯定会有自己的事件循环,我认为不能沿着copas的循环运行。
因此,要通过http进行异步下载文件,我是否必须同时找到一个支持异步http和异步文件IO的包?或者其他的想法?
发布于 2022-04-14 06:54:09
在阅读了一堆代码之后,我终于可以回答我自己的问题了。
正如我在对这个问题的评论中提到的,我们可以使用异步IO库导出的step函数,并将多个步骤合并到一个更大的循环中。
对于luv,它使用C中的外部线程池来管理文件IO,并使用一个单线程循环来调用挂起的回调和管理IO轮询(在我的用例中不需要轮询)。
可以简单地调用luv提供的文件操作函数来生成异步文件IO。但仍然需要执行luv的循环来调用回调,绑定到IO操作。
integerated主循环如下所示:
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
endcopas.step()是copas的步进函数。uv.run("nowait")使luv只运行一次事件循环,如果在轮询时没有就绪IO,则不要阻塞。
一个可行的解决方案如下:
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()https://stackoverflow.com/questions/71858620
复制相似问题