Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional promises

In my script, I need to retrieve a dictionary to convert encoded values into names:

$.ajax({
    // retrieve dictionary
})
.done(function(dictionary){
    // convert encoded values into names
})
.done(function(){
    // run my application
});

However, sometimes the dictionary has already been loaded by another application, and in this case I don't need the ajax call:

if (dictionary) {
    // convert encoded values into names
    // run my application
}
else {
$.ajax({
    // retrieve dictionary
})
.done(function(dictionary){
    // convert encoded values into names
})
.done(function(){
    // run my application
});
}

This if/else statement is rather heavy, is there a way to make it shorter:

// load dictionary if needed
// then run my application

Note: I used the $ sign for my pseudo-code, but I am not necessarily tied to jQuery.

like image 388
Christophe Avatar asked Sep 30 '13 16:09

Christophe


3 Answers

You should call $.ajax() exactly once, and store the returned promise in your (global-ish) dictionary variable.

Then, every time you want to use the result, just write dictionary.then(...).
If the AJAX request already finished, the callback will run immediately.

like image 143
SLaks Avatar answered Oct 13 '22 16:10

SLaks


This is the pattern I generally use:

var done = function() {
    //continue loading application
}

if(!dictionary) {
    $.ajax({

    })
        .done(done);
} else {
    done.apply(this);
}

A very similar pattern, that always makes use of a deferred object, could be the following:

var 
    dictionaryDeferred = new $.Deferred(),
    dictionaryPromise = dictionaryDeferred.promise();

if(!dictionary) {
    $.ajax({

    })
        .done(function() {
            //do something with the response
            dictionaryDeferred.resolve();
        });
} else {
    dictionaryDeferred.resolve();
}

dictionaryPromise.then(function() {
    //continue loading application
});
like image 33
Adam Avatar answered Oct 13 '22 15:10

Adam


Maybe create a bogus promise with $.when?

var promise;
if (dictionary) promise = $.when(dictionary);
else {
    promise = $.ajax({

    })
    .done(function(dictionary){
        // convert encoded values into names
    });
}

promise
    .done(function(){
        // run my application
    });
like image 1
Adam Zielinski Avatar answered Oct 13 '22 16:10

Adam Zielinski