How to write the response from a network.request() to a variable?

I’ve read everything that I can find about this in the forums and the docs, and clearly I’m missing something important, but I have no idea what it is.

I’m sending a GET request to a network device and I want to save its response in a variable that I can use. Starting from the sample code in https://docs.coronalabs.com/api/library/network/request.html, I’ve created the following code snippet:

local function networkListener( event ) if( event.isError ) then print( "Network error: ", event.response) else print( "In networkListener, RESPONSE: " .. event.response ) zumlink\_response = event.response end end -- This stuff is useful if you're going to do a get. local headers = {} headers["Content-Type"] = "application/x-www-form-urlencoded" headers["Accept-Language"] = "en-US" headers["Authentication"] = "admin:admin" local body = "color=red&size=small" local params = {} params.headers = headers params.body = body -- Return a string which is the JSON object. -- Let the calling function sort it out. function zumlink.cmd( ip, command ) local cmd = {} cmd.command = command local url = "http://admin:admin@" .. ip .. "/cli/" .. cmd.command print( url ) network.request( url, "GET", networkListener, params ) print( "In zumlink.cmd: zumlink\_response is [" .. zumlink\_response .. "]" ) return zumlink\_response end

So, the calling function calls zumlink.cmd(), passing it the IP address of the connected device and the command “systemInfo”. As zumlink.cmd() exits, it prints the contents of zumlink_response , which is empty because networkListener() hasn’t executed yet. It also passes the empty zumlink_response to the calling function. Then the networkListener() executes, and writes a value to zumlink_response.

If I execute the calling function again, we go through the same routine, but this time  zumlink_response  already contains something, and so **zumlink.cmd() **prints the contents of  zumlink_response and passes it to the calling function. Then the networkListener() executes and writes a new value to  zumlink_response. (In the printout below, the new value is identical to the old value, but that’s just coincidence.)

Here’s the output:

-- The line at 16:15:02.385 is the output from "print( url )" in my code snippet. -- It's just there to tell me what was sent to the connected device. 16:15:02.385 http://admin:admin@192.168.137.32/cli/systemInfo 16:15:02.396 In zumlink.cmd: zumlink\_response is [] 16:15:02.396 systemInfo retval is [] 16:15:02.568 In networkListener, RESPONSE: [{"RESPONSE":{"pages":{"systemInfo":{"deviceConfiguration":"R1","deviceFirmwareVersion":"FWT1314TB.8","deviceId":"1","deviceModel":"Z9-PE2","deviceName":"","hopTableVersion":"SET0101HT","layoutHash":"2902858855","licenses":"Custom Apps","modelCode":"0","radioFirmwareVersion":"FWT1072TR.43","radioModel":"AMT0100AA","radioModelCode":"0","radioSerialNumber":"4026803732","resetInfo":"","rteTemplateVersion":"FWT1311TP.3","rteVersion":"FWT1311TP.3","serialNumber":"4026803732","themeVersion":"FWT1314TB.8"}}},"RESULT":{"MESSAGE":"OK","RESULT":0}}] 16:15:02.568 -- Second time through. Again, the line at 16:15:25.785 is the "print( url )" output. 16:15:25.785 http://admin:admin@192.168.137.32/cli/systemInfo 16:15:25.785 In zumlink.cmd: zumlink\_response is [[{"RESPONSE":{"pages":{"systemInfo":{"deviceConfiguration":"R1","deviceFirmwareVersion":"FWT1314TB.8","deviceId":"1","deviceModel":"Z9-PE2","deviceName":"","hopTableVersion":"SET0101HT","layoutHash":"2902858855","licenses":"Custom Apps","modelCode":"0","radioFirmwareVersion":"FWT1072TR.43","radioModel":"AMT0100AA","radioModelCode":"0","radioSerialNumber":"4026803732","resetInfo":"","rteTemplateVersion":"FWT1311TP.3","rteVersion":"FWT1311TP.3","serialNumber":"4026803732","themeVersion":"FWT1314TB.8"}}},"RESULT":{"MESSAGE":"OK","RESULT":0}}] 16:15:25.785 ] 16:15:25.785 systemInfo retval is [[{"RESPONSE":{"pages":{"systemInfo":{"deviceConfiguration":"R1","deviceFirmwareVersion":"FWT1314TB.8","deviceId":"1","deviceModel":"Z9-PE2","deviceName":"","hopTableVersion":"SET0101HT","layoutHash":"2902858855","licenses":"Custom Apps","modelCode":"0","radioFirmwareVersion":"FWT1072TR.43","radioModel":"AMT0100AA","radioModelCode":"0","radioSerialNumber":"4026803732","resetInfo":"","rteTemplateVersion":"FWT1311TP.3","rteVersion":"FWT1311TP.3","serialNumber":"4026803732","themeVersion":"FWT1314TB.8"}}},"RESULT":{"MESSAGE":"OK","RESULT":0}}] 16:15:25.785 ] 16:15:25.954 In networkListener, RESPONSE: [{"RESPONSE":{"pages":{"systemInfo":{"deviceConfiguration":"R1","deviceFirmwareVersion":"FWT1314TB.8","deviceId":"1","deviceModel":"Z9-PE2","deviceName":"","hopTableVersion":"SET0101HT","layoutHash":"2902858855","licenses":"Custom Apps","modelCode":"0","radioFirmwareVersion":"FWT1072TR.43","radioModel":"AMT0100AA","radioModelCode":"0","radioSerialNumber":"4026803732","resetInfo":"","rteTemplateVersion":"FWT1311TP.3","rteVersion":"FWT1311TP.3","serialNumber":"4026803732","themeVersion":"FWT1314TB.8"}}},"RESULT":{"MESSAGE":"OK","RESULT":0}}] 16:15:25.954 

So I know what’s happening, and I know why it’s happening. I know that I need to wait for networkListener() to write to  zumlink_response. But I don’t  know how. It doesn’t matter to me whether the wait is blocking or non-blocking. How do I do it? What am I missing? I’m sure it’s something simple …

If you want to block the entire thing you can use a while loop. Stay in the loop until the variable is not null. Not sure if this will block the listener, but I don’t think so.

while zumlink\_response == nil do -- Nothing. end

It would be better if you don’t block. Fire the event and then just wait for the response before doing whatever you are doing. The response can call whatever you are calling after the event returns. Show some UI that says it is waiting for a response. A spinner. Anything really.

In your code  zumlink_response  is global so therefore it’s state is persistent.  You also cannot return the response to a network request in the code block - requests are not blocking. 

You are also going to need a callback function to send the data too.  So you need a function in your scene that can accept (and process) the response.  So when you call sendComand() you would show a spinner or some feedback to the user and cancel this in your callback function.

Something like this

local callbackFunction local function networkListener( event ) if not event.isError print( "In networkListener, RESPONSE: " .. event.response ) callbackFunction(event.response) \<-- send response to callback function -passed into sendComand() end end function sendCommand( ip, command, callback ) local cmd = {} cmd.command = command local url = "http://admin:admin@" .. ip .. "/cli/" .. cmd.command callbackFunction = callback \<-- cache callback network.request( url, "GET", networkListener, params ) end

It worked. Thanks to @agramonte and @SGS for your help.