协程,在Lua中实现多个请求。

我已经研究了这个主题12个小时了,但是似乎没有什么头绪。我甚至不知道这是否可行,但我希望它可以,因为这会对延续我的项目有很大帮助。

我正在尝试创建协程,以便所使用的程序不会因为不能执行异步http请求而卡死。我已经搞清楚如何实现这一点,尽管我的协程理解还处于“嗯?它是怎么工作的?”阶段。我的问题现在是能够对多个请求做出正确响应。例如,以下应该会产生三个独立的响应:

foo(a)
foo(b)
foo(c)

其中,'foo'使用内部参数启动协程。如果所有请求单独请求,则返回正确的结果。但是,如果请求为一个块,则只返回'foo(c)'的结果。现在,我理解这背后的原因,但我不能找到一种使其以块形式请求时返回所有三个结果的方法。为了帮助理解这个问题,这里是实际的代码:

function background_weather()
local loc = url.escape(querystring)
weatherpage = http.request("http://api.wunderground.com/api/004678614f27ceae/conditions/q/" .. loc .. ".json")
wresults = json.decode(weatherpage)
--在这里处理一些内容,主要是数据挖掘
end
--将数据挖掘的信息作为响应发送
coroutine.yield()
end

和协程的创建:

function getweather ()
-- 看看后台程序是否在运行
  if background_task == nil or
   coroutine.status (background_task) == "dead" then
-- 不在运行,创建它
   background_task = coroutine.create (background_weather)
-- 设置定时器以保持它运行
 AddTimer ("tickler", 0, 0, 1, "",
           timer_flag.Enabled + timer_flag.Replace,
           "tickle_it")
  end  -- 如果
end -- 函数

'querystring'变量使用初始请求设置。我没有在这里包含它,但出于测试的目的,将'querystring'变量设置为“12345”。计时器是脚本的原始作者初始化的东西,以检查协程是否仍在运行,每秒对后台进行轮询,直到完成。说实话,我甚至不确定我是否做得正确,尽管它在程序中异步运行。

因此,是否可能在一个块中接收多个请求并返回多个正确的响应?或者这对Lua来说太过艰巨了?

点赞
用户312586
用户312586

Coroutines 不是这样工作的。它们实际上是阻塞式的。

Coroutines 解决的问题是:“我想要一个可以执行一段时间的函数,然后回到做其他事情的状态,然后再回来时恢复原来的状态。”

注意,我并没有说:“我想它在我做其他事情时继续运行”,代码的流“停留”在 coroutine 上,只有当您回到它时才会继续执行。

使用 coroutines,您可以修改(在某些情况下可以协助)代码的行为,使其更加清晰和可读。但它仍然是严格的单线程模型。

请记住,Lua 实现必须在 C99 中指定。由于此标准没有附带线程实现,Lua 默认是严格的单线程模型。如果您需要多线程,需要将其挂接到外部库。例如,luvit 将 Luajit 钩接到 libuv 库中以实现此功能。

一些好的参考资料:

2012-07-15 11:48:58
用户1516484
用户1516484

Programming in Lua 的第 9.4 章节包含一个非常好的例子,展示如何使用协程和 LuaSocket 的 socket.select() 函数来解决这个问题,以避免繁忙的循环。

不幸的是,我不相信有任何方法使用 socket.select 函数与 socket.http 函数一起使用;PiL 示例中的代码通常就足够满足需求,但它并没有处理某些常见情况,比如请求的 URL 发送了一个重定向。

2012-07-15 20:34:08