28

This should be a simple one. I have a function that is called and I need to wait for all the async operations to complete. what I want is something like this...

self.processSchema(data).done(function(results){ //do stuff});

The processSchema function loops using $.each and calls an async method.

var processSchema = function(data)
{
     var def = new $.Deferred();
     $.each(table, function()
     {
         //calls an async SQLitePlugin method
         db.executeSql(sql, data, function(tx, results){
            def.resolve(results);
         }
     }

     return(def.promise());
}

This does not seem to work, I am new to $.Deferred so any guidance would be helpful

gdex
  • 465
  • 1
  • 4
  • 10
  • I think you would need a new deferred for every single db.executeSql, and then do a large $.when(deferred1, deferred2...defferedN).then(function(data1, data2...dataN) { }); – Robin Giltner Dec 19 '13 at 18:17

2 Answers2

37

You'll need a promise for each iteration

var processSchema = function(data) {
     var promises = [];

     $.each(table, function() {
         var def = new $.Deferred();
         db.executeSql(sql, data, function(tx, results){
            def.resolve(results);
         });
         promises.push(def);
     });

     return $.when.apply(undefined, promises).promise();
}
adeneo
  • 312,895
  • 29
  • 395
  • 388
  • adeneo, should that return defcon.promise() ? – gdex Dec 19 '13 at 18:24
  • 1
    Yes it should! One could return the array of promises, but to keep the syntax of how the OP want's to call the function, I figure one master promise that is returned and then resolved when all the other promises are resolved would be easier, and then pass all the returned data as the arguments array directly ? – adeneo Dec 19 '13 at 18:28
  • @Jan Dvorak, so the def.apply will work inside of loop? – gdex Dec 19 '13 at 18:31
  • 2
    @adeneo actually you can simply return result of `$.when`, without creating "master" promise? – hawk Dec 19 '13 at 18:35
  • @hawk Because you actually *want* to return a Promise, not a Deferred. Because Promises are read-only. – Tomalak Dec 19 '13 at 18:38
  • @gdex `apply` takes an array and uses it as a list of arguments. `$.when` takes a list of promises and returns a promise that resolves when all arguments resolve – John Dvorak Dec 19 '13 at 18:38
  • 2
    @Tomalak `$.when.apply(...).promise()` – John Dvorak Dec 19 '13 at 18:39
  • @hawk - indeed you could, as chaining `done` on the function call would be the same as chaining `then` on the `$.when`, and as Jan points out, just adding `promise()` returns the promise and would be the same as the master deferred. – adeneo Dec 19 '13 at 18:40
  • For what it's worth, it would be safer to pass `$` as the context to `apply`. We don't know if `$.when` uses `this` internally, but if it does we want it pointing to `$`, hence `$.when.apply($, promises).promise()`. – Milosz Dec 19 '13 at 18:47
  • Using the `apply().then` gives me an argument array of each deferred result which may be helpful in my scenario. The `.promise()` only returns the last result which is fine in some cases. I appreciate the help! – gdex Dec 19 '13 at 18:52
  • @gdex - that's actually true, then() would return an array of results, which could be useful. – adeneo Dec 19 '13 at 18:54
8

For Functional Programming fiends (like myself), here's a single-expression version of adeneo's answer:

var processSchema = function(data) {
    return $.when.apply($, $.map(table, function() {
        var def = new $.Deferred();
        db.executeSql(sql, data, function(tx, results){
            def.resolve(results);
        });
        return def;
    })).promise();
};

Also I'd like to note that you are iterating over table, but aren't doing anything with each item in the iteration (i.e. the callback in your each has no arguments.) Now, I'm not sure what your goal is, but this doesn't seem right to me :P

Community
  • 1
  • 1
Milosz
  • 2,924
  • 3
  • 22
  • 24
  • There is a lot more to the function then I posted, for brevity I did not include some of the non essential stuff... – gdex Dec 19 '13 at 19:06