This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
surferpup's profile picture

[SOLVED] Problem using http.get() from within Coroutines

Started by surferpup, 12 January 2014 - 01:08 AM
surferpup #1
Posted 12 January 2014 - 02:08 AM
I read Bubba's Advanced Lua Topics - Coroutines (found here http://www.computerc...ics-coroutines/–thanks Bubba) and Lyqyd's responses to my questions (thanks Lyqyd). I then tried to implement coroutines into my Real World / MinecraftWorld Time Display Program which I posted in Programs (here http://www.computerc...isplay-program/).

While the program works better with coroutines implemented (it has fewer hiccups on startup and chunk reloading), I had to abandon full implementation of coroutines because of the http.get() command. I use this line of code to refresh the time from http://www.timeapi.org:

time[i].time=(http.get("http://www.timeapi.org/"..(time[i].zone).."/now?format=%25l:%25M%20%25p").readAll())

The code is correct, and it does properly refresh the time values I am displaying. However, using http.get() appears to cause the coroutine to yield, although I did not expect this behavior. I had to move this code out of the coroutine and into its own function (refreshTime() in my program). As a result, my code does not really take full advantage of coroutines.

I do not want to repeat the post of my code here, so instead I will link to the pastebin: http://pastebin.com/AUQfZjRK

Am I doing something wrong?
Edited on 30 January 2014 - 12:54 AM
Alice #2
Posted 12 January 2014 - 02:17 AM
My guess why it yields is because when you use http.get() it probably sends a signal to that page then waits for a file or an error. That wait might cause the yield.

Don't quote me on it, I'm just now learning how to use both http api and coroutine api.
surferpup #3
Posted 12 January 2014 - 02:27 AM
That was my first thought as well. However, I would have expected that on an http.request() which is asynchronous. http.get() is synchronous and is not supposed to return until it has either loaded the page or failed to do so. I must be missing something.
theoriginalbit #4
Posted 12 January 2014 - 02:39 AM
http.get does yield, so does http.post, the only one that does not is http.request, however you must make your own event loop for this.

here is the code directly from the bios.lua file so you can see that both http.get and http.post yield

-- Install the lua part of the HTTP api (if enabled)
if http then
  local function wrapRequest( _url, _post )
    local requestID = http.request( _url, _post )
    while true do
      local event, param1, param2 = os.pullEvent()
      if event == "http_success" and param1 == _url then
        return param2
      elseif event == "http_failure" and param1 == _url then
        return nil
      end
    end 
  end

  http.get = function( _url )
    return wrapRequest( _url, nil )
  end

  http.post = function( _url, _post )
    return wrapRequest( _url, _post or "" )
  end
end
surferpup #5
Posted 12 January 2014 - 03:16 AM
Thank you. That is very helpful. Of course, if I am to handle my own event loop for the http.request(), it too will cause my coroutine to yield (won't it?) I will have to think more on this.
theoriginalbit #6
Posted 12 January 2014 - 03:21 AM
yes indeed it will. however with ComputerCraft you have to yield or else the mod will terminate your program. as a note other calls that yield are:
  • coroutine.yield (obviously)
  • os.pullEvent
  • os.pullEventRaw
  • read
  • sleep
  • http.get and http.post
  • turtle api except for turtle.getItemCount, turtle.getItemSpace and turtle.getFuelLevel
  • rednet.receive
  • gps.locate (due to using rednet)
  • anything else that asks for user input
Edited on 12 January 2014 - 02:21 AM
surferpup #7
Posted 12 January 2014 - 03:24 AM
Thank you again. I will have to experiment on how to effectively use coroutines (at least I am starting to use them now).
surferpup #8
Posted 12 January 2014 - 12:36 PM
I have worked to make my Real World / MinecraftWorld Time Display Program work well however, for some reason, it sometimes will not run as the startup program when the computer turns on – it just sits there. If I stop it and run it from the shell, it runs fine. Can anyone see what I am doing wrong?

Program located on this forum here -> http://www.computerc...isplay-program/

Pastebin -> http://pastebin.com/AUQfZjRK

I refresh the time variables with the refreshTime() routine, set up two coroutines, fire off my initial timers then start my main loop. Not sure where it is failing to follow through. A fresh set of eyes (and better talent) would be greatly appreciated.
Edited on 12 January 2014 - 11:36 AM
Lyqyd #9
Posted 12 January 2014 - 12:52 PM
Threads merged.
surferpup #10
Posted 12 January 2014 - 01:17 PM
Strangely enough, the program works fine in my single-player environment. However in my multi-player (same Unleashed version) it hangs on boot up, but will run fine when executed from shell.
surferpup #11
Posted 12 January 2014 - 02:16 PM
This is a non-problem. It is simply related to the variable amount of time it takes for http.get() to resolve. The code is working. I edited out one piece of inneficiency where I called refreshTime(0 once too often.

Sorry for the trouble.