Jump to content




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


  • You cannot reply to this topic
10 replies to this topic

#1 surferpup

  • Members
  • 286 posts
  • LocationUnited States

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 by surferpup, 30 January 2014 - 01:54 AM.


#2 Alice

  • Members
  • 429 posts
  • LocationBehind you.

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.

#3 surferpup

  • Members
  • 286 posts
  • LocationUnited States

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.

#4 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

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


#5 surferpup

  • Members
  • 286 posts
  • LocationUnited States

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.

#6 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

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 by theoriginalbit, 12 January 2014 - 03:21 AM.


#7 surferpup

  • Members
  • 286 posts
  • LocationUnited States

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).

#8 surferpup

  • Members
  • 286 posts
  • LocationUnited States

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 by surferpup, 12 January 2014 - 12:36 PM.


#9 Lyqyd

    Lua Liquidator

  • Moderators
  • 8,465 posts

Posted 12 January 2014 - 12:52 PM

Threads merged.

#10 surferpup

  • Members
  • 286 posts
  • LocationUnited States

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.

#11 surferpup

  • Members
  • 286 posts
  • LocationUnited States

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.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users