1

I was working on a simple application that makes sequential ajax calls, passing result of first call into the next one.

Of course I don't want to go into the callback hell, and therefore look into Promises/A+ spec example and Q library.

I have prepared an async function that should result in what I want. But I want an insight on how I can simplify the Sequential promise passing.

For now I am still reading on how to best work with promises and deferred objects, so forgive me for the very naive code.

So now I am looking at two things:

  • the way to simplify the sequencing of promises (that depend on one another as in my case)
  • suggestions

    var modifyableObject = {
        toProcess : ["one", "two", "three", "four", "five"]
    }
    
    
    function returnsDeferredResults(someResult) {
    
        var deferred = Q.defer();
    
        // my async function (setTimeout for now will do, $.ajax() later)
        setTimeout(function () {
    
            var nextResult = (someResult || " Initial_Blank_Value ") + "..." + modifyableObject.toProcess[0]; 
    
            modifyableObject.toProcess = modifyableObject.toProcess.splice(1);
    
            console.log("New Tick Result: ", nextResult, "Array: ", modifyableObject.toProcess);
    
            deferred.resolve( nextResult);
    
        }, 200);
    
        return deferred.promise;
    }
    
    
    //$("#test_promise").click(function () {
    
        function getDeferredResult(prevResult) {
            return returnsDeferredResults(prevResult);
        }
    
        var prevResult = getDeferredResult();
    
        var nextTick = "";
    
        for (var i = modifyableObject.toProcess.length; i > 1; i --) {
    
            if (nextTick) 
                nextTick = nextTick.then(getDeferredResult);
            else 
                nextTick = prevResult.then(getDeferredResult);
        }
    
        //nextTick.fin(function(){ ...});
    
    //});
    
    
    
    /*
    New Tick Result:   Initial_Blank_Value ...one           Array:  ["two", "three", "four", "five"]
    New Tick Result:   Initial_Blank_Value ...one...two            Array:  ["three", "four", "five"]
    New Tick Result:   Initial_Blank_Value ...one...two...three             Array:  ["four", "five"] 
    New Tick Result:   Initial_Blank_Value ...one...two...three...four              Array:  ["five"]
    New Tick Result:   Initial_Blank_Value ...one...two...three...four...five             Array:  [] 
    */
    

Thank you everyone in advance!

Plyto
  • 741
  • 1
  • 9
  • 18
  • I don't really get why you're using promises here. Their point should be not to need globals like `modifyableObject` any more. – Bergi Jul 03 '13 at 15:59
  • this is just a prototype code that is simplified and put into "global" scope. I will use `$.ajax()` instead of `setTimeout` function and `modifyableObject` will be replaced with data that I need to pass into the `$.ajax()` call. – Plyto Jul 03 '13 at 18:43

1 Answers1

5

You can simplify your loop by combining the two variables:

var nextTick = getDeferredResult();

for (var i = modifyableObject.toProcess.length; i > 1; i --) {
    nextTick = nextTick.then(getDeferredResult);
}

Or,

return modifyableObject.toProcess.reduce(function(promise, item) {
    return promise.then(getDeferredResult);
}, Q.resolve());

You can simplify your function too:

return Q.delay(200).then(function) { 
    return "..." + modifyableObject.toProcess.shift();
});

jQuery AJAX also returns a promise, which Q is compatible with (in recent versions of jQuery)

You can then combine the two improvements by passing each item to the function:

return modifyableObject.toProcess.reduce(function(promise, item) {
    return promise.then(processItem.bind(null, item));
}, Q.resolve());

function processItem(item) {
    return Q.delay(200).then(function) { 
        return "..." + modifyableObject.toProcess.shift();
    });
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 1
    wow, such an awesome response! I really like the way you use reduce function on promise and push then method on it. This is what I was looking for :P – Plyto Jul 03 '13 at 18:36
  • This is such an awesome pattern; it should be documented in the Q docs, IMO. – Will Oct 08 '13 at 21:00