spo spo - 5 months ago 8
jQuery Question

How to pass data through mapped promises?

I have a three stage mashup script that checks newest rentals from the local video shop and then gets their critics percentages and concensus from Rotten Tomatoes (RT):

$(document).ready(function(){
$('button').click(function (){
getNewRentals(url).then(function(ids){
var mapped = ids.map(function(id, f){
return function(){
return getRentalSpecs(id, f).then(function (f, name, year){
return getRotten(f, name, year); // Gets only f!
});
}
});
var m = mapped[0]();
for(var i = 1; i < mapped.length; i++) {
m = m.then(mapped[i]);
}
});
});
});


All is well, except that only f is passed to the last function getRotten, but not film name nor year. There must be something wrong with the mapping loop, because all three functions use indentical jquery getJSON's (via Yahoo YQL) identically wrapped inside standard js promises that identically resolve to params mentioned in the code. So if the data is passed from the 1st function to the 2nd, why not from the 2nd to the 3rd as well?

I've been roasting in this callback/promise hell for a few weeks now and am pretty blistered by now. This is also my first post to SO, so please bear with me.

Answer

A promise represents a single value, which is passed as one argument to any then handler. Use an object or array where you need to pass multiple values (whichever is more appropriate):

$(document).ready(function () {
    $('button').click(loadRotten);
});

function loadRotten () {
    return getNewRentals(url)
        .then(function (ids) {
            return Promise.all(ids.map(getRentalSpecs));
        })
        .then(function (objects) {
            return Promise.all(objects.map(function (obj) {
                return GetRotten(obj.f, obj.name, obj.year);
            });
            // Or refactor `GetRotten` to accept a single object
            // return Promise.all(objects.map(GetRotten));
        });
    });
}

You will have to amend getRentalSpecs so that it resolves with an object with the properties f, name, and year.

I have refactored your code to use Promise.all(), which makes it easier to understand. It did not seem necessary to map to function expressions and call each of these in sequence manually, as they do not depend on each other.

Comments