Lua忽略范围变量

时间:2017-05-20 01:41:57

标签: lua esp8266 nodemcu

这可能是一个愚蠢的问题,但是,我不知道发生了什么。

我有一个提取谷歌时间的简单脚本,我需要将其设置为time全局变量。因此,在receive事件中,我打印所提取的时间并且它正常工作。

问题是变量time在事件外部调用时始终为空。这是代码:

-- test.lua
time = ""

function getTime()
  conn = net.createConnection(net.TCP, 0)

  conn:connect(80,'google.com')
  conn:on("connection", function(conn, payload)
    conn:send("HEAD / HTTP/1.1\r\n"..
          "Host: google.com\r\n"..
          "Accept: */*\r\n"..
          "User-Agent: Mozilla/4.0 (compatible; esp8266 Lua;)"..
          "\r\n\r\n"
    )
  end)

  conn:on("receive", function(conn, payload)
    conn:close()
    time = string.sub(payload,string.find(payload,"Date: ")
       +6,string.find(payload,"Date: ")+35)
    end)
    print("testing: " .. time) -- WORKS!
end

getTime()
print("variable: ".. time)

以下是我如何调用该函数(使用nodemcu-uploader终端):

➜  test nu terminal
--- Miniterm on /dev/cu.wchusbserial1410  115200,8,N,1 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---

> dofile('lib/test.lua')
variable:
> testing: Sat, 20 May 2017 01:37:35 GMT

任何帮助都会非常感激! 感谢

2 个答案:

答案 0 :(得分:2)

看起来范围很好。查看输出打印的顺序。

conn:connectcon:on接受函数,因为它们是异步的。 getTime()只是在被调用之前返回。

答案 1 :(得分:1)

  

NodeMCU编程模型类似于Node.js,仅在Lua中。它是异步和事件驱动的。因此,许多函数都有回调函数的参数。

来源:https://github.com/nodemcu/nodemcu-firmware/#programming-model

这意味着接受回调函数作为参数的函数是非阻塞。它返回意味着您不能逐行读取一段代码并期望它按此顺序执行。

因此,原始程序中的事件序列大致为:

  • getTime被触发但未阻止
  • print("variable: ".. time)已执行。此时time仍为空。
  • 建立与google.com的连接。
  • HEAD请求已发送至google.com。
  • 响应是接收和接收事件处理程序(即匿名回调函数)启动。
  • time已填充。

我看到两个明显的修复,一个使用全局time变量,另一个没有。两者都基于pass-callback-function-as-parameter模式。

请注意,在触发这些事件(conn:on)之前,您应始终设置事件侦听器(在您的情况下为conn:connect,以避免遗漏某些事件。你的代码

conn:connect(80,'google.com')
conn:on("connection"...

仅适用,因为conn:connect是非阻塞的,因为在建立连接之前需要一些时间。到发生这种情况时,on-connection事件处理程序已经注册。

保持全局变量

time = ""

function getTime(cb)
  conn = net.createConnection(net.TCP, 0)

  conn:on("connection", function(socket, payload)
    socket:send("HEAD / HTTP/1.1\r\n" ..
            "Host: google.com\r\n" ..
            "Accept: */*\r\n" ..
            "User-Agent: Mozilla/4.0 (compatible; esp8266 Lua;)" ..
            "\r\n\r\n")
  end)

  conn:on("receive", function(socket, payload)
    socket:close()
    time = string.sub(payload, string.find(payload, "Date: ")
            + 6, string.find(payload, "Date: ") + 35)
    print("time inside on-receive: " .. time)
    cb()
  end)

  conn:connect(80, 'google.com')
end

function do_something_with_time()
  print("time inside callback: " .. time)
end

getTime(do_something_with_time)

没有全局变量

function getTime(cb)
  conn = net.createConnection(net.TCP, 0)

  conn:on("connection", function(socket, payload)
    socket:send("HEAD / HTTP/1.1\r\n" ..
            "Host: google.com\r\n" ..
            "Accept: */*\r\n" ..
            "User-Agent: Mozilla/4.0 (compatible; esp8266 Lua;)" ..
            "\r\n\r\n")
  end)

  conn:on("receive", function(socket, payload)
    socket:close()
    local time = string.sub(payload, string.find(payload, "Date: ")
            + 6, string.find(payload, "Date: ") + 35)
    print("time inside on-receive: " .. time)
    cb(time)
  end)

  conn:connect(80, 'google.com')
end

function do_something_with_time(time)
  print("time inside callback: " .. time)
end

getTime(do_something_with_time)