0

I'm having a bit of trouble with jQuery Deferred.

I'm using a jQuery ajax call inside a function wrapper, and I'm attempting to chain two success callbacks one after the other, in order of scope. However, both success callbacks are executing simultaneously, which is causing problems.

My initial function call looks like this (system.log is a smarter console.log.):

serverpaths.setConfig(path).then(system.log("BAM! SERVERPATHS: " + serverpaths));

Inside this setConfig method, I have an AJAX call with a .then() chained to it. (system.defer is a wrapper that returns a jQuery.Deferred object; http.get is a wrapper for jQuery.ajax.)

config.setConfig = function (configObj) {
    var that = this;
    var inlineHelper = function (data) {
        return system.defer(function (dfd) {
            for (var key in data) {
                system.log("Config[" + key + "]: " + that[key]);
                system.log("Data[" + key + "]: " + data[key]);
                that[key] = data[key];
                system.log("New Config[" + key + "]: " + that[key]);
            }
        }).promise();
    };

    if (typeof configObj === "string") {
        http.get("api/getPathConfig")             // The problem seems to be in this area
            .then(function (data) {
                return system.defer(function () {
                    inlineHelper(data);
                }).promise();
            });
    } else {
        return system.defer(function () {
            inlineHelper(configObj);
        }).promise();
    }
};

Ideally, the ajax request should be called, then inlinehelper should be called, then system.log should be called, because I'm kicking my promise object back up the chain with return statements. The problem here is that the ajax request is called, and then system.log and inlinehelper are called simultaneously.

Has anyone run into a problem like this before? Function scope and async calls seem to be fighting each other here. I'm sure I can figure this out, but it doesn't seem quite logical - my guess is that when my ajax request fires its success, that triggers the .then() call in my main scope without me wanting it to. I'm sure I could solve this, but it helps to have a great community of devs to bounce thoughts off of.

I appreciate all of your advice. Thank you!

1 Answers1

0

Doing .then(function() { return promise }) just does nothing. Your returned promise won't be propagated to the next deferred callback.

If you want to do this, use .pipe() instead of .then(). This way you will be able to chain promises.

If you want to chain 3 asynchronous call, do like this :

firstDeferredCall.pipe(secondDeferredCall).pipe(thirdDeferredCall)

If you write

firstDeferredCall.then(secondDeferredCall).then(thirdDeferredCall)

thirdDeferredCall won't wait for secondDeferredCall call to be executed.

Edit: as tim said, .pipe is deprecated since jQuery 1.8.

If you are using jQuery 1.8+, you can use .then which now replaces .pipe. See documentation for .then. In this case your code should be good without any modification.

Mordhak
  • 2,646
  • 2
  • 20
  • 14
  • as far as I know, `.pipe()` is being deprecated. http://api.jquery.com/deferred.pipe/ – tim Jul 17 '13 at 22:32