Trace
Trace

Reputation: 18869

Async.js return promise

I'm using the async.js library to achieve an stream of asynchronous requests.
The code below works fine.

async.each( 
    //--- Collection of models to save ---// 
    collSaveData, 
    function(model, callback){ 
        model.save([], {success: function(){ 
            callback(); 
        }}); 
    }, 
    function(err){ 
        console.log('finished'); 
    }); 

How can I return a promise?

I mean, something in a fashion like this:

var promise = async.each( 
    //--- Collection of models to save ---// 
    collSaveData, 
    function(model, callback){ 
        model.save([], {success: function(){ 
            callback(); 
        }}); 
    }, 
    function(err){ 
        console.log('finished'); 
    }); 

Upvotes: 0

Views: 205

Answers (2)

nikoshr
nikoshr

Reputation: 33344

You probably don't need async.js to issue you calls and synchronize them. Combine the objects returned by Model.save with $.when to produce a general promise :

var promises = _.invoke(collSaveData, 'save');
var promise = $.when.apply(null, promises);
promise.then(function() {
    console.log('all done');
});

And a Fiddle http://jsfiddle.net/nikoshr/Z3Ezw/

You can customize how you handle the responses from each save, for example:

var promises = _.map(collSaveData, function(m) {
    return m.save().then(function(response) {
        console.log('saved', m);
    });
});

The key is to return a promise for each model. http://jsfiddle.net/nikoshr/Z3Ezw/2/

Upvotes: 1

Quince
Quince

Reputation: 14990

Not actually used async before but looking through the docs it makes no reference to returning a promise so you would have to wrap the asyn.each with a function that did return a promise and then the success/error callback could then just resolve or reject that promise

here is a quick example that should work

//wrap the async each and return a promise from this call
var promiseAsync = function(openfiles, saveFile) {
    var defer = $.Deferred();
    async.each(
        openfiles, saveFile, function(err) {
            if (err) {
                defer.reject(err);
            } else {
                defer.resolve();
            }
        });
    return defer.promise();
}

//now it can be used like a normal promise
var promise = promiseAsync(collSaveData, function(model, callback) {
    model.save([], {
        success: function() {
            callback();
        }
    });
});

$.when(promise).done(function(){
    //whatever
}).fail(function(err){
    //error
});

make promiseAsync available throughout your app (attach it to Backbone somewhere, underscore mixin,helper/utility module??) and then you can always use it.

Update: fiddle based on @nikoshr's fiddle (for setting up the page) (going to start using fiddles over code pen now like the fact you can have a console in the browser) http://jsfiddle.net/leighking2/7xf7v/

Upvotes: 1

Related Questions