Titanium Community Questions & Answer Archive

We felt that 6+ years of knowledge should not die so this is the Titanium Community Questions & Answer Archive

make sure httpClient onload function finished

how can i assure that the onload function of a httpclient is executed completely before the app continues with other stuff?

i want to download ten xml-files but i am not interested in ten different httpclients, so i want to wait until the download finishs and then start the next one.

— asked December 5th 2010 by dev 1605
  • events
  • httpclient
  • onload
  • xhr
3 Comments
  • httpClient performs asynchronously. It cannot perform synchronous calls (which is what you seem to want). You would have to chain the request, testing for some response from the onload function, and initiate and call the next httpclient request. One way to do it would be to use the ondatastream method testing for 100% completion by setting a content length header in the response from the server.

    — commented December 5th 2010 by Patrick Glass
  • Yeah, I'm having a hell of a time with this.

    I'm creating a process that downloads a bunch of files (tens to hundreds) in a batch operation.

    I can't lock up the UI in any way, because the user could still navigate through it during the operation (browsing records, etc…). So I migrated everything out into a worker script.

    My worker does the following:

    • loads a list of fileIDs to download into an array
    • unshifts() a fileID from the array stack, and
    • send that fileID to the downloadFile() function (which then postMessage()s back to parent depending on what happens, in order to refresh a status message in the UI

    The problem is that, yes, httpClient cannot run synchronously (which leaves me wondering what the third argument in the .open() method is for…). :(

    If I manage the array in the parent script, postMessage()ing to download the next one in the array only if "file.size === httpClient.getResponseHeader('Content-Length')", that doesn't do me much good, because if the user refreshes the UI by doing something, the process is halted (because the parent script is reloaded.

    If, however, I manage the array entirely in my worker script, running it in the background, the HTTPClient objects are loaded asynchronously, and everything locks up.

    Plus, I don't have access to setInterval() or setTimeout() in my worker, which kind of stinks, so that kind of workaround isn't readily available to my worker.

    I'm also stuck on how to find and kill a stuck HTTPClient connection (using HTTPClient.abort()), but that's probably another topic.

    Has anyone successfully done this? The above post seems pretty close…

    — commented December 10th 2010 by Joshua Pruitt
  • Plus the fact that Perl's '-s' file test operator seems to return different results from the server than Titanium.Filesystem.File.size(), which makes the content-length header method unreliable… :(

    — commented December 10th 2010 by Joshua Pruitt

5 Answers

  • i found a great asynchronous solution http://developer.appcelerator.com/question/35991/multiple-httpclient-get-requests-asynchronous#72411

    — answered December 17th 2010 by dev 1605
    permalink
    0 Comments
  • you can fire an event when the httpClient request has finished.

    the receiver of the event can then initiate a new httpClient request.

    I can provide additional details in the suggestion is not clear.

    — answered December 5th 2010 by Aaron Saunders
    permalink
    0 Comments
  • This is UNTESTED, and I am not sure I am folowing you, but would something like this work?

    var count = 0;
    var receivedFiles = [];
    
    //fire off all requests
    request(1, callback);
    request(2, callback);
    ...
    request(10, callback);
    
    function callback() {
       //results come back in any order
       //only continue after last result
       receivedFiles.push('the file');
       count++;
       if (count >= 10) {doRemainingStuff()}
    }
    
    function doRemainingStuff() {
       //the rest of the logic is inside this function
    }
    
    — answered December 15th 2010 by Stan Silver
    permalink
    1 Comment
    • Or, if you want to "lock" the parent script while the worker script is "working":

      function parentBefore() {...}
      function parentAfter() {...}
      parentBefore();
      loadFiles(parentAfter);
      
      function loadFiles(fCallback) {
         //do stuff
         fCallback();
      }
      

      In other words, put the normal "flow" of the file inside functions, then somehow "chain" the functions. Again, I am not sure if this is what you are looking for, and again it is not tested….

      — commented December 15th 2010 by Stan Silver
  • Hi 'dev'

    There is a 'synchronous' mode for HTTPClient. I believe it's enabled as follows…

    xhr.open("GET","http://myservice/data.json",true);
    

    (you can check that in / iphone / Classes / TiNetworkHTTPClientProxy.m under https://github.com/appcelerator/titanium_mobile)

    I use asynchronous with a 'collector' function to establish when all are done, as Stan described above. But then I only have 3-6 requests and prefer to fire them asap to reduce wait time.

    cheers,
    Chris.

    — answered December 15th 2010 by Chris Reed
    permalink
    1 Comment
    • async only works on ios and mobile web not android.

      — commented January 31st 2013 by Andrew Blair
  • nice idea stan, but no idea what "request" needs to look like.. the problem is to fire that callback event i think

    — answered December 17th 2010 by dev 1605
    permalink
    0 Comments
The ownership of individual contributions to this community generated content is retained by the authors of their contributions.
All trademarks remain the property of the respective owner.