barfoo
barfoo

Reputation: 97

jQuery deferred:

I have a function. The inside of the function looks like:

if (isNewCustomer) {
    doSomething();
    cleanup();
}
else {
    $.getJSON(..., function(result) {
        doSomethingElse();
        cleanup();
    });
}

I was hoping I could simply this by using deferred. My attempt looks like:

var do_it = doSomething;

if (!isNewCustomer) {
    do_it = $.getJSON(..., function(result) {
        doSomethingElse();
    });
}

$.when(do_it).done(function() {
    cleanup();
});

But this isn't working. What am I doing wrong?

EDIT: Renaming variable do to do_it. This isn't the problem with the code. The problem is that when do_it is doSomething, doSomething doesn't get executed.

Upvotes: 0

Views: 465

Answers (4)

timlint
timlint

Reputation: 157

Check out this jsfiddle https://jsfiddle.net/timlint/tg7xqtha/

Using Deferred is the way to go. It's a little hard to grasp the flow sometimes and how to pass data around but this example may give you some insight.

You can almost think of a deferred as a flag. in a function you create a deferred object.

the function returns the .promise() for that deferred. this allows you to call the function doSomething(bool).done() and do something once it finishes. You resolve the deferred when you know the task is complete and it won't be called until then.

function doSomething(isNewCustomer)
{

// think of a deferred as a flag object in a way
var d = $.Deferred();


if(!isNewCustomer)
{
    $.getJSON(..., function(result) {
        // work with data
    }).done(function() {
        // finisn up data

        // set deferred to resolved
        d.resolve();
    });
}
else
{
    // some business logic

    // set deferred to resolved
    d.resolve();   
}
// returning the promise lets you call .done()
// on this function call in the main call
return d.promise();
}

Upvotes: 0

Jason
Jason

Reputation: 3179

You need an explicit Deferred. If you pass when() an argument that is not a Deferred, the function is invoked immediately, and is probably why you're getting unexpected results.

var deferred = $.Deferred();

if (isNewCustomer) {
    deferred.resolveWith(doSomething());
}
else {
    $.getJSON(...).
        done(function(result) {
            deferred.resolveWith(doSomethingElse(result));
        }).
        fail(function(...) {
            deferred.rejectWith(...);
        });
}

deferred.promise().always(function() { cleanup(); });

Upvotes: -1

Julian Aubourg
Julian Aubourg

Reputation: 11436

var result;

if (isNewCustomer) {
    result = doSomething();
} else {
    result = $.getJSON( ..., function( data ) {
        doSomethingElse( data );
    });
}

$.when( result ).done(function() {
    cleanup();
});

See the code above: you never called the function just like Gigi pointed out.

Upvotes: 1

Gigi
Gigi

Reputation: 4962

do is a keyword in javascript, so better rename the variable.

var do_it = doSomething;

if (!isNewCustomer) {
    do_it = $.getJSON(..., function(result) {
        doSomethingElse();
    });
}
//          || << note me
$.when(do_it()).done(function() {
    cleanup();
});

Upvotes: 3

Related Questions