problems with network.request

Hello everyone

In my app I am trying to communicate with the server and want to know how to wait for the response from the sever. I post a bit of code to explain:

Corona

local json = require ( "json" ) local myNewData local decodedData local function networkListener( event ) if ( event.isError ) then print( "Network error!" ) else myNewData = event.response print ( "From server: " .. myNewData ) decodedData = ( json.decode( myNewData ) ) end end local function searchMovie( title ) title = title or "" tesTab = {} --possible tables local body = "titleMovie="..title.."&tesTab ="..tesTab local params = {} params.headers = headers params.body = body network.request( "http://mySite//getMovie.php", "POST", networkListener, params ) if(decodedData) then --my code end end searchMovie("Back to the Future")

In server (getMovie.php)

\<?php $host = "hostName"; $username = "user"; $password = "pass"; $database = "my\_DB"; $title = $\_POST["titleMovie"]; $conn = mysql\_connect($host, $username, $password) or die ("Not conn server"); mysql\_select\_db("$database", $conn) or die ("Not select DB"); $interrogation = "SELECT \* FROM Movies WHERE title = '$titolo' "; $resultInterrogation = mysql\_query($interrogation); $json = array(); if(mysql\_num\_rows($resultInterrogation)) { while($row = mysql\_fetch\_row($resultInterrogation)) { $json[] = $row; } } mysql\_close($database); echo json\_encode($json); ?\>

of course, it will never enter into the condition (decode is true) because of the response times.

I have two questions:

1-How can I fix?

2-Is the best way?

The basic idea is that you need to move the “my code” part up to the networkListener function – until that function fires (i.e. receives data) there is no data to do anything with.  Beyond that, unfortunately, the answer is “it depends” … what kind of work is going on in “my code”?

Thanks for the answer

I was wondering if there was a better way to call methods from networkListener.

My code is structured thus:

-scenaMenu which takes the title of the film was added by the user

-scenaResults that first extract the data via the call to php and then displays them on the screen

then I could make more efficient the lua code and/or php?

A bit more info might be helpful …

In scenaMenu, it sounds like you have a newTextField that the user enters the film title, and probably a “submit” button?  When the submit button is pressed, you’re calling function searchMovie … which eventually calls networkListener when data finally comes back.  My guess is that when networkListener is called, and has valid data, you want to do composer.gotoScene( “scenaResults” ) where the data will be displayed (maybe on a network-error, you want to display an error message and let the user enter a new title).

Is that about right?

Exact

Precisely I do so in the main scene take the title from TextField and when the user presses confirmation save the title.

composer.setVariable ("titleMovie" TextField .text)

After which I run composer.goToScene (“scene.Results” ").

In sceneResult recover the title

composer.getVariable( "titleMovie" )

and send the request to the php file (as it has done in the code at the beginning).

According to the data of the response I upgrade the content and location of display object in the scene.

Made myself clear? Should I add something? thanks again

So there are other possible improvements?

Have you tried moving the gotoScene call up inside networkListener?  (near the “decodedData =” part)

One issue I could think of is that, generally, you want your networkListener code to be “small” (or at least fast), and I have no idea what the gotoScene function call involves.  It seems to do it’s main “work” by firing a sequence of events, so maybe it’s fine.

Maybe someone from Corona can weigh in on whether it’s a good idea to do gotoScene from inside networkListener?  maybe it should be put into a timer/delay?

Well I guess that call gotoScene inside the networkListener is not the best thing. Later I should make other requests, and I can not change the scene for each request. I decided to put a timer but I can’t, because the server response time is so variable you may have errors. (O unnecessary delays at best).

Surely there is something better, do not think is an unusual procedure…

Generally for any call back type listener, if you’re going to do something that impacts the parent, you want to drop that action into a short lived timer so the call back function can complete then whatever action happens after the call back function is done.

A prime example of this is you have an object that generates a physics collision. Inside the collision handling function, you try and remove the object. This is generally cause an error and the solution is to wrap the object removal inside a timer:

timer.performWithDelay(10, function() display.remove( event.target ); end, 1)

10 millseconds is enough time for the collision handling function to finish and then you can destroy the object.

I’ve seen instances where this can also impact network.request(). If something isn’t working right, like going to a new scene, then drop it into a timer and see if that helps. Other than that, there really isn’t much of a need to not do work inside the request unless you’re queueing up many requests in which case you want them to finish as quickly as possible.

Rob

So in essence the new code should be so:

local json = require ( "json" ) local myNewData local decodedData local function networkListener( event ) if ( event.isError ) then print( "Network error!" ) else myNewData = event.response print ( "From server: " .. myNewData ) decodedData = ( json.decode( myNewData ) ) end end local function searchMovie( title ) title = title or "" tesTab = {} --possible tables local body = "titleMovie="..title.."&tesTab ="..tesTab local params = {} params.headers = headers params.body = body network.request( "http://mySite//getMovie.php", "POST", networkListener, params ) timer.performWithDelay(10, function() --my code end, 1) end searchMovie("Back to the Future")

it’s right?

php and that’s okay?

thanks again and sorry Rob just that I’m a little confused

local json = require ( "json" ) local myNewData local decodedData local function networkListener( event ) if ( event.isError ) then print( "Network error!" ) else myNewData = event.response print ( "From server: " .. myNewData ) decodedData = ( json.decode( myNewData ) ) -- my code that can and should happen now. timer.performWithDelay(10, function() --my code that needs to happen after the listener completes end, 1) end end local function searchMovie( title ) title = title or "" tesTab = {} --possible tables local body = "titleMovie="..title.."&tesTab ="..tesTab local params = {} params.headers = headers params.body = body network.request( "http://mySite//getMovie.php", "POST", networkListener, params ) end searchMovie("Back to the Future")

Ok perfectly, thanks again for your time rob

The basic idea is that you need to move the “my code” part up to the networkListener function – until that function fires (i.e. receives data) there is no data to do anything with.  Beyond that, unfortunately, the answer is “it depends” … what kind of work is going on in “my code”?

Thanks for the answer

I was wondering if there was a better way to call methods from networkListener.

My code is structured thus:

-scenaMenu which takes the title of the film was added by the user

-scenaResults that first extract the data via the call to php and then displays them on the screen

then I could make more efficient the lua code and/or php?

A bit more info might be helpful …

In scenaMenu, it sounds like you have a newTextField that the user enters the film title, and probably a “submit” button?  When the submit button is pressed, you’re calling function searchMovie … which eventually calls networkListener when data finally comes back.  My guess is that when networkListener is called, and has valid data, you want to do composer.gotoScene( “scenaResults” ) where the data will be displayed (maybe on a network-error, you want to display an error message and let the user enter a new title).

Is that about right?

Exact

Precisely I do so in the main scene take the title from TextField and when the user presses confirmation save the title.

composer.setVariable ("titleMovie" TextField .text)

After which I run composer.goToScene (“scene.Results” ").

In sceneResult recover the title

composer.getVariable( "titleMovie" )

and send the request to the php file (as it has done in the code at the beginning).

According to the data of the response I upgrade the content and location of display object in the scene.

Made myself clear? Should I add something? thanks again

So there are other possible improvements?

Have you tried moving the gotoScene call up inside networkListener?  (near the “decodedData =” part)

One issue I could think of is that, generally, you want your networkListener code to be “small” (or at least fast), and I have no idea what the gotoScene function call involves.  It seems to do it’s main “work” by firing a sequence of events, so maybe it’s fine.

Maybe someone from Corona can weigh in on whether it’s a good idea to do gotoScene from inside networkListener?  maybe it should be put into a timer/delay?

Well I guess that call gotoScene inside the networkListener is not the best thing. Later I should make other requests, and I can not change the scene for each request. I decided to put a timer but I can’t, because the server response time is so variable you may have errors. (O unnecessary delays at best).

Surely there is something better, do not think is an unusual procedure…

Generally for any call back type listener, if you’re going to do something that impacts the parent, you want to drop that action into a short lived timer so the call back function can complete then whatever action happens after the call back function is done.

A prime example of this is you have an object that generates a physics collision. Inside the collision handling function, you try and remove the object. This is generally cause an error and the solution is to wrap the object removal inside a timer:

timer.performWithDelay(10, function() display.remove( event.target ); end, 1)

10 millseconds is enough time for the collision handling function to finish and then you can destroy the object.

I’ve seen instances where this can also impact network.request(). If something isn’t working right, like going to a new scene, then drop it into a timer and see if that helps. Other than that, there really isn’t much of a need to not do work inside the request unless you’re queueing up many requests in which case you want them to finish as quickly as possible.

Rob