Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Waiting for coroutine to finish before main function continues
Started by Ryan Abrahams Aug 29 2019 06:14 AM

4 replies to this topic
coroutine wait network.request()

Best Answer XeduR @Spyric , 29 August 2019 - 07:33 PM

This is a common mistake with asynchronous functions.

What you should do is exactly what ammar71 already suggested.

 

Here's some sample code with explanations, copied almost directly from the docs.

local function updateValues( args )
    -- Optional function for updating values based on a successful network request.
end

local function networkListener( e )
 
    if ( e.isError ) then
        print( "Network error: ", e.response )
        -- The network request failed, so you can let the user know to try again later.
    else
        print ( "RESPONSE: " .. e.response )
        -- The network request has finished successfully, so do whatever you want in here.
        -- Or, call another function from here to do what you need, e.g. updateValues( e.response )
    end

end

-- Once this network request finishes, it will automatically call the listener. No need for coroutines.
network.request( "https://encrypted.google.com", "GET", networkListener )

[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

Ryan Abrahams

[GLOBAL: userInfoPane.html]
Ryan Abrahams
  • Observer

  • 5 posts
  • Corona SDK

Hi All,

 

I am currently in a bit of a pickle. I have implemented an SSL network request as per the page: https://docs.coronalabs.com/api/library/network/request.html

 

I want to populate the variable response with json.decode(event.response), which I can do perfectly fine after calling network.request( URL , "GET", networkListener ) [url hidden for obvious reasons]

 

Updating for clarification:

 

I have a single scene that is used for altering a data entry, it has three functions: new record, edit the current record before committing, and edit a record that has already been committed to the database.

if type(composer.getVariable("entry_edit")) == "nil" or composer.getVariable("entry_edit") == "0" then
description_box = "" -- brand new, so is set to blank string
elseif composer.getVariable("entry_edit") == "1" then
description_box = composer.getVariable("desc") -- this is from the previous scene
elseif composer.getVariable("entry_edit") == "2" then
local URL = "https://blah.blah" -- the url goes here
network.request( URL , "GET", networkListener )
-- ideally this should wait here until networkListener is FINISHED
description_box = response[i]['description'] -- this is retrieved from the pairs response from a database
end

-- the further in the scene, this runs

desctextbox= native.newTextField( device.centerX+device.centerX*0.5, display.actualContentHeight*0.25, display.actualContentWidth*0.4, font.contentFontSize*1.4 )
desctextbox.inputType="no-emoji"
desctextbox.text = description_box -- put in here what ever is relevant, according to the script above

The problem is that lua/corona is getting to the desctextbox creation earlier prior to the networkListener completing, because locally creating the scene is taking less than 2-4ms, while the response from the webserver is taking up to 200ms. So when the scene is trying to create the textbox, if I am in the

composer.getVariable("entry_edit") == "2"
mode, then I am trying to set an undeclared value (at that point in time, description_box is a nil value, because it has not been declared yet.

 

 

So yeah. The previous developer was using http socket connections, which can wait for a response, but this was sending usernames and passwords over clear text, which is not acceptable to the client, thus I am migrating to https, but that operates differently to the http socket connection. So now I have to wait for a response before the rest of the lua script/main routine continues.

 

 

Hope that someone might be able to point me in the right direction.

 

Cheers

Ryan Abrahams



[TOPIC: post.html]
#2

ammar71

[GLOBAL: userInfoPane.html]
ammar71
  • Enthusiast

  • 49 posts
  • Corona SDK

Hi Ryan,

 

Not sure I understand the question correctly, but can't you put all the code that populates the page into a function and call that function after the response has been recieved?



[TOPIC: post.html]
#3

Ryan Abrahams

[GLOBAL: userInfoPane.html]
Ryan Abrahams
  • Observer

  • 5 posts
  • Corona SDK

Hi Ammar,

 

I have updated the description of the problem that might hopefully clarify what the problem is, and what I need to do.

 

 

Regards

Ryan Abrahams



[TOPIC: post.html]
#4

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 893 posts
  • Corona SDK

  Best Answer

This is a common mistake with asynchronous functions.

What you should do is exactly what ammar71 already suggested.

 

Here's some sample code with explanations, copied almost directly from the docs.

local function updateValues( args )
    -- Optional function for updating values based on a successful network request.
end

local function networkListener( e )
 
    if ( e.isError ) then
        print( "Network error: ", e.response )
        -- The network request failed, so you can let the user know to try again later.
    else
        print ( "RESPONSE: " .. e.response )
        -- The network request has finished successfully, so do whatever you want in here.
        -- Or, call another function from here to do what you need, e.g. updateValues( e.response )
    end

end

-- Once this network request finishes, it will automatically call the listener. No need for coroutines.
network.request( "https://encrypted.google.com", "GET", networkListener )


[TOPIC: post.html]
#5

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,820 posts
  • Corona SDK

In addition to that, you can either:

 

1) Draw your text fields, image rects but display placeholder info/images until the response is received.

2) Don't draw these and display some kind of loading message/busy indicator to show the app is working, only draw them when the data is available

3) Draw them but hide them until the response is received, showing a message/busy indicator in the meantime.




[topic_controls]
[/topic_controls]

Also tagged with one or more of these keywords: coroutine, wait, network.request()