Using loop and cascade network.request

Thanks in advance for your answers. The situation is the following:

  1. I must process N times some records stored locally in sqlite

  2. To process each record I must make a first network.request to a web service 01 and once this first request is finished , I must make a second network.request to a web service 02

  3. I have tried to condense the code in this (N=3):

    – TEST WS local json = require (“json”) print (os.date()…" -------------- TEST WS START --------------------") local function wsTest02Call( event ) if ( event.isError ) then print( “Network error: “, event.response ) else print ( os.date()…” RESPONSE: " … event.response ) end end local function wsTest01Call( event ) if ( event.isError ) then print( “Network error: “, event.response ) else print ( os.date()…” RESPONSE: " … event.response ) local response = json.decode( event.response ) if (response.Status ==“ok”) then local headers = {} headers[“Content-Type”] = “application/x-www-form-urlencoded” headers[“Accept-Language”] = “en-US” headers[“User-Agent”] = “My Corona APP” local body = “qty=50&priceunit=100” local params = {} params.headers = headers params.body = body params.timeout = 15 – Call WS02 network.request( “https://aws05.phonemas.com/ws/wstest02.php”, “POST”, wsTest02Call, params ) end end end local function callWS( ) local headers = {} headers[“Content-Type”] = “application/x-www-form-urlencoded” headers[“Accept-Language”] = “en-US” headers[“User-Agent”] = “My Corona APP” local body = “color=red&size=small” local params = {} params.headers = headers params.body = body params.timeout = 15 – CAL WS01 network.request( “https://aws05.phonemas.com/ws/wstest01.php”, “POST”, wsTest01Call, params ) end – LOOP 3 TIMES for i=1,3 do callWS() end print (os.date()…” -------------- TEST WS END --------------------”)

The result is as follows:

Copyright © 2009-2018  C o r o n a   L a b s   I n c .

Version: 3.0.0

Build: 2018.3228

Loading project from:   ~/Documents/Corona Projects/Samples/Test WS

Project sandbox folder: ~/Library/Application Support/Corona Simulator/Test WS-81A8676CBB0C22A036E551B82F6EBB38

Platform: GT-I9300 / x86_64 / 10.12.6 / Intel HD Graphics 4000 OpenGL Engine / 2.1 INTEL-10.25.19 / 2018.3228 / en-CO | CO | en_CO | en

Mon Mar 12 08:16:08 2018 -------------- TEST WS START --------------------

Mon Mar 12 08:16:08 2018 -------------- TEST WS END --------------------

Mon Mar 12 08:16:11 2018 RESPONSE: {“Status”:“ok”,“info”:“MSG: Thank you. Processed requirement 01)”}

Mon Mar 12 08:16:11 2018 RESPONSE: {“Status”:“ok”,“info”:“MSG: Thank you. Processed requirement 01)”}

Mon Mar 12 08:16:11 2018 RESPONSE: {“Status”:“ok”,“info”:“MSG: Thank you. Processed requirement 01)”}

Mon Mar 12 08:16:15 2018 RESPONSE: {“Status”:“ok”,“info”:“MSG: Thank you. Processed requirement 02)”}

Mon Mar 12 08:16:15 2018 RESPONSE: {“Status”:“ok”,“info”:“MSG: Thank you. Processed requirement 02)”}

Mon Mar 12 08:16:15 2018 RESPONSE: {“Status”:“ok”,“info”:“MSG: Thank you. Processed requirement 02)”}

It is observed that they are not being executed as I need it (point 2).

The question is: How should I adjust my code to run in cascade (one behind the other)?

The URLs in the code are real and public, for those who wish to review.

Regards,

Solón

a straight sequencial network calls function the way i do it (conceptual logic, not actual code)

local url="your\_url" local function callback(event) if event.reply then your code (perhaps storing result in a table) if there is a second call to be made url="your\_new\_url OR your\_modified\_url" network.request(url,callback) else no more call desired so can exit function end else handle no reply, if reply was expected if if no more results is a desired end of function, exit function end end network.request(url,callback)

Thanks Anaqim for your quick response.

According to your code, I should not have 2 listener functions separately, if not build a single listener. Is that correct?

Regards,

Solon

That is all you need whether you do a single call or several sequencial calls.

The second and subsequent network calls are made from within the listener function.

Thats what makes this call loop sequencial.

Headers will usually be the same, so declare them at the top with the url, although you can easily set all new parameters in the reply just before making the next call.

Hope that makes sense.

Thanks again Anaqim. Your help has been very important.

I have to adjust the scripts of the webservices (PHP) for it.

Regards,

Solon

Happy to help mate

Hope it works out for you  :slight_smile:

Greetings Anaqim.

I have already configured the process of running the ws in cascade, according to your suggestion.

I have not yet been able to get that process to run in a loop (The real case is that I’m going through a sqlite database and I have to process each record)

Can you suggest something to run in a loop?

Thank you,

Solon

PS: I did not have to modify the PHP scripts, only Corona sdk.

Hi there,

If you are talking about processing each record received from the network call agains a local sqllite base, that is easy.

Show me the relevant code bit with you network call and I’ll see if I notice anything

Thanks again,

Without the FOR-LOOP, it can be seen that the cascade process works for a call. This is the code for test:

-- TEST WS local json = require ("json") print (os.date().." -------------- WS 01 START --------------------") -- WS Headers local headers = {} headers["Content-Type"] = "application/x-www-form-urlencoded" headers["Accept-Language"] = "en-US" headers["User-Agent"] = "My Corona APP" -- Functions local function wsTest02Call( event ) if ( event.isError ) then print( "Network error: ", event.response ) else print ( os.date().." RESPONSE: " .. event.response ) print (os.date().." -------------- WS 02 END --------------------") end end local function wsTest01Call( event ) if ( event.isError ) then print( "Network error: ", event.response ) else print ( os.date().." RESPONSE: " .. event.response ) local response = json.decode( event.response ) if (response.Status =="ok") then local body = "qty=50&priceunit=100" local params = {} params.headers = headers params.body = body params.timeout = 15 print (os.date().." -------------- WS 01 END --------------------") print (os.date().." -------------- WS 02 START --------------------") network.request( "https://aws05.phonemas.com/ws/wstest02.php", "POST", wsTest02Call, params ) end end end -- Variables local N = 3 -- # records in local DB --for i=1,N do print("Procesing Record #") local body = "color=red&size=small" local params = {} params.headers = headers params.body = body params.timeout = 15 -- CAL WS01 network.request( "https://aws05.phonemas.com/ws/wstest01.php", "POST", wsTest01Call, params ) --end

Hi,

Being the fact that network calls are asynchronous, when you issue them in a loop like that is just going to call all of the requests in one go.

You would need to implement a queuing system of some type using another table and then process each call as the response is returned.

-dev

which is what my code above does.

i call it making them sequencial, meaning call 2 doesnt trigger before call 1 has replied, call 3 doesnt trigger until call 2 has replied, and so on.

Hi,

I could be totally wrong here, but from what I gather, there is a set of sqlite records, and each one needs to make basically 2 network calls per record, in sequence, which the code @anaqim posted does indeed handle.

The issue is that you can’t just run a for loop over the database records and and call the network requests.

--for i=1,N do print("Procesing Record #") local body = "color=red&size=small" local params = {} params.headers = headers params.body = body params.timeout = 15 -- CAL WS01 network.request( "https://aws05.phonemas.com/ws/wstest01.php", "POST", wsTest01Call, params ) --end

The requests will be coming back at different times, and most likely will overlap in places.

You would need to gather all the database record data into a table array and then call the request per each entry and wait for the response before issuing the next request set. You could do this using the requestId returned from the network call for example.

Again, I could be totally misunderstanding the use case.

-dev

Thanks to Anaqim and Develephant for your answers.

Finally I solved the problem, passing the data from the sqlite table to a lua table, and from there I launch the process with a button (widget) for each record (row of the lua table).

Regards,

Solca

Pressing a button for each record isnt optimal is it? Unless you have only a few records.

Why not put the button event code on a timer instead? :slight_smile:

Or add a score field, and then it’s a game.  :smiley:

-dev

Your comment is correct.

For practical purposes of the use case that I am solving, it is fine.

In another scenario (like batch) maybe not.

Thanks again.

How could this be?

Got me a good laugh today, thx dev :grinning:
Solca, glad if it helps. Have a great one!

Im sorry i dont get the question

a straight sequencial network calls function the way i do it (conceptual logic, not actual code)

local url="your\_url" local function callback(event) if event.reply then your code (perhaps storing result in a table) if there is a second call to be made url="your\_new\_url OR your\_modified\_url" network.request(url,callback) else no more call desired so can exit function end else handle no reply, if reply was expected if if no more results is a desired end of function, exit function end end network.request(url,callback)