Waiting for a Function to return from an object

I am sure there is something conceptual I am just not getting but after days of messing around I need someone far smarter than me to tell me how I can do things.

I basically want to wait for a function in a table to return a result and then continue on with the code. So accept it works asynchronously but deal with it.

I have done a cut down example which I hope will explain what I mean.

manager.lua 

local manager = {} local manager\_mt = { \_\_index = manager } function manager:new() return setmetatable( manager, manager\_mt ) end function manager:upload() local function networkListener( event ) if ( event.isError ) then print( "Network error!") return false elseif ( event.phase == "ended" ) then print ( "Upload complete!" ) return true end end return network.upload( "http://127.0.0.1/restapi.php", "POST", networkListener, "object.json", system.DocumentsDirectory, "application/json" ) end return manager

main.lua

local manager = require("manager") manager = manager:new() if(manager:upload()==true) then print("Yippee, upload has been completed, do the next thing") end

So I am basically looking to find out if “manager:upload()” has been successful and respond accordingly. I am trying to take an OO approach to things. I have used network.upload just as an example, it could be a number of different things.

Is what I am trying to do possible, do I have to do it a totally different way in Lua?

Any help would be greatly appreciated.

Thanks :slight_smile:

network.upload doesn’t return any thing.  Also it’s asynchronous and returns right away.  You have to adapt to having the call complete later and not test for a “return code”.

Rob

There really isn’t a “sleep” type function that would allow a function style return of a value to work.  He clearly could do something in his handler when the download finishes to generate another event back into his code.

But what I would do is have the manager:new() function take a listener parameter, i.e.:

manager = manager:new(myManagerListener)

Then when network.request() finishes and it’s listener gets called and it’s the end of the request event, simply construct a table of information about the request and then call the passed in myManagerListener() function with the table.  That way the calling object doesn’t have to know anything about the doings of the manager class and you’ve got a function in your object that gets the data.

Rob

Thanks for the feedback Rob.

I have been bashing my head against the wall trying to come up with an elegant solution to it. All the examples I can find do all this sort of thing just in the main.lua. They do not try to break it out. This obviously makes life easier for demo purposes.

I thought about calling a dynamic function in main.lua to get things moving along again but this is obviously a flawed approach. Can you give me a little pointer as to how I should be thinking about this sort of issue, what approach to take.

Thanks

Edit - looks like. I was typing at the same time :slight_smile:

Ok, so am I right in thinking that I should be creating a listener object in main.lua. I update this in the manager.lua with the relevant outcome. I then use the updating of the listener object to do the next thing? Or have I got that totally wrong?

  local function uploadComplete( event )      print("Yippee, upload has been completed, do the next thing") end     local manager = require("manager") manager = manager:new( uploadComplete ) manager:upload()

local manager = {} local manager\_mt = { \_\_index = manager }   function manager:new( listener )     manager.listener = listener     return setmetatable( manager, manager\_mt ) end   function manager:upload()       local function networkListener( event )         if ( event.isError ) then             if manager.listener then                   local myEvent = { isError = true, didComplete = false }                   manager.listener( myEvent )             end             print( "Network error!")             return false         elseif ( event.phase == "ended" ) then             print ( "Upload complete!" )             if manager.listener then                   local myEvent = { isError = false, didComplete = true }                   manager.listener( myEvent )             end             return true         end     end       return network.upload(         "http://127.0.0.1/restapi.php",         "POST",         networkListener,         "object.json",         system.DocumentsDirectory,         "application/json"         ) end   return manager

 

or something like that.

 

Rob

Thank you, that is fab. :slight_smile: Will have a play in the morning.

Very nice code snippet. Quite a tutorial worthy subject too if I may say so!  :wink:

Just in case anyone else comes across this Robs modest “or something like that” worked exactly how I needed. Once again thanks for the help Rob  :) 

Quite welcome.  When I say “or something like that” it basically means I don’t know the inner workings of your code and you may need to modify to fit.  :wink:

Rob

network.upload doesn’t return any thing.  Also it’s asynchronous and returns right away.  You have to adapt to having the call complete later and not test for a “return code”.

Rob

There really isn’t a “sleep” type function that would allow a function style return of a value to work.  He clearly could do something in his handler when the download finishes to generate another event back into his code.

But what I would do is have the manager:new() function take a listener parameter, i.e.:

manager = manager:new(myManagerListener)

Then when network.request() finishes and it’s listener gets called and it’s the end of the request event, simply construct a table of information about the request and then call the passed in myManagerListener() function with the table.  That way the calling object doesn’t have to know anything about the doings of the manager class and you’ve got a function in your object that gets the data.

Rob

Thanks for the feedback Rob.

I have been bashing my head against the wall trying to come up with an elegant solution to it. All the examples I can find do all this sort of thing just in the main.lua. They do not try to break it out. This obviously makes life easier for demo purposes.

I thought about calling a dynamic function in main.lua to get things moving along again but this is obviously a flawed approach. Can you give me a little pointer as to how I should be thinking about this sort of issue, what approach to take.

Thanks

Edit - looks like. I was typing at the same time :slight_smile:

Ok, so am I right in thinking that I should be creating a listener object in main.lua. I update this in the manager.lua with the relevant outcome. I then use the updating of the listener object to do the next thing? Or have I got that totally wrong?

  local function uploadComplete( event )      print("Yippee, upload has been completed, do the next thing") end     local manager = require("manager") manager = manager:new( uploadComplete ) manager:upload()

local manager = {} local manager\_mt = { \_\_index = manager }   function manager:new( listener )     manager.listener = listener     return setmetatable( manager, manager\_mt ) end   function manager:upload()       local function networkListener( event )         if ( event.isError ) then             if manager.listener then                   local myEvent = { isError = true, didComplete = false }                   manager.listener( myEvent )             end             print( "Network error!")             return false         elseif ( event.phase == "ended" ) then             print ( "Upload complete!" )             if manager.listener then                   local myEvent = { isError = false, didComplete = true }                   manager.listener( myEvent )             end             return true         end     end       return network.upload(         "http://127.0.0.1/restapi.php",         "POST",         networkListener,         "object.json",         system.DocumentsDirectory,         "application/json"         ) end   return manager

 

or something like that.

 

Rob

Thank you, that is fab. :slight_smile: Will have a play in the morning.

Very nice code snippet. Quite a tutorial worthy subject too if I may say so!  :wink:

Just in case anyone else comes across this Robs modest “or something like that” worked exactly how I needed. Once again thanks for the help Rob  :) 

Quite welcome.  When I say “or something like that” it basically means I don’t know the inner workings of your code and you may need to modify to fit.  :wink:

Rob