Q:

return after a series of functions in javascript

I have tried to do this with q as well as async, but haven't been able to seem to make it work. After trying those I tried my own way. I didn't think this would work, but I thought I would give it a try. I am confused since there is a callback within a callback in a sense. Here is the function I am wanting to do:
var getPrice = function(theData) {
var wep = theData.weapon;
var completed = 0;
for (i = 0; i < theData.skins.length; i++) {
    var currSkin = theData.skins[i];
    theData.skinData[currSkin] = {};
    for (k = 0; k < wears.length; k++) {
        csgomarket.getSinglePrice(wep, currSkin, wears[k], false,
            function(err, data) {
                completed++;
                if (!err) {
                    theData.skinData[data.skin][data.wear] = data;
                }
                if (completed === theData.skins.length*wears.length) {
                        return theData;
                    }
            })
        }
    }
}

I know these kinds of issues are common in javascript as I have ran into them before, but not sure how to solve this one. I am wanting to fill my object with all the data returned by the method:
csgomarket.getSinglePrice(wep, currSkin, wears[k], false,
  function(err, data) { });

Since each call to getSinglePrice() sends off a GET request it takes some time for the responses to come back. Any suggestions or help would be greatly appreciated!

A:

First csgomarket.getSinglePrice() needs to be promisified. Here's an adapter function that calls  csgomarket.getSinglePrice() and returns a Q promise.
function getSinglePriceAsync(wep, skin, wear, stattrak) {
    return Q.Promise(function(resolve, reject) { // may be `Q.promise(...)` (lower case P) depending on Q version.
        csgomarket.getSinglePrice(wep, skin, wear, stattrak, function(err, result) {
            if(err) {
                reject(err);
            } else {
                resolve(result);
            }
        });
    });
}

Now, you want getPrice() to return a promise that settles when all the individual getSinglePriceAsync() promises settle, which is trivial :
var getPrice = function(theData) {
    var promises = [];//array in which to accumulate promises 
    theData.skins.forEach(function(s) {
        theData.skinData[s] = {};
        wears.forEach(function(w) {
            promises.push(getSinglePriceAsync(theData.weapon, s, w, false).then(function(data) {
                theData.skinData[data.skin][data.wear] = data;
            }));
        });
    });
    //return a single promise that will settle when all the individual promises settle.
    return Q.allSettled(promises).then(function() {
        return theData;
    });
}

However, theData.skinData[data.skin][data.wear] will simplify slightly to  theData.skinData[s][w] :
var getPrice = function(theData) {
    var promises = [];//array in which to accumulate promises 
    theData.skins.forEach(function(s) {
        theData.skinData[s] = {}; // 
        wears.forEach(function(w) {
            promises.push(getSinglePriceAsync(theData.weapon, s, w, false).then(function(data) {
                theData.skinData[s][w] = data;
            }));
        });
    });
    //return a single promise that will settle when all the individual `promises` settle.
    return Q.allSettled(promises).then(function() {
        return theData;
    });
}

This simplification would work because the outer forEach(function() {...}) causes s to be trapped in a closure.
As getPrice() now returns a promise, it must be used as follows :
getPrice(myData).then(function(data) {
    // use `data` here.
}).catch(function(e) {
    //something went wrong!
    console.log(e);
});

