在javascript中返回一系列函数之后

我曾试图用q和async来做到这一点,但似乎无法使其工作。 试过后,我尝试了我自己的方式。 我不认为这会起作用,但我想我会试一试。 我感到困惑,因为在某种意义上,callback中存在callback。 这是我想要做的function:

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; } }) } } } 

我知道这些types的问题在JavaScript中很常见,因为我之前遇到过这些问题,但不知道如何解决这个问题。 我想要用方法返回的所有数据填充我的对象:

 csgomarket.getSinglePrice(wep, currSkin, wears[k], false, function(err, data) { }); 

由于每次调用getSinglePrice()都会发送一个GET请求,因此响应需要一段时间才能返回。 任何build议或帮助将不胜感激!

首先csgomarket.getSinglePrice()需要promisified。 这里有一个调用函数csgomarket.getSinglePrice()并返回一个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); } }); }); } 

现在,你想要getPrice()返回一个承诺,当所有的个人getSinglePriceAsync()承诺解决,这是微不足道的:

 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; }); } 

但是, theData.skinData[data.skin][data.wear]会稍微简化为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; }); } 

这种简化将会起作用,因为forEach(function() {...})会导致s被困在闭包中。

由于getPrice()现在返回一个承诺,它必须如下使用:

 getPrice(myData).then(function(data) { // use `data` here. }).catch(function(e) { //something went wrong! console.log(e); }); 

你的方法非常复杂。

我认为最好的办法是做所有的价格1请求。 现在,对于每一个价格你做一个请求。 如果你有一个需要请求的数据的列表(数组),返回值应该是一个包含价格的列表。

如果上面的方法是不可能的,你可以阅读更多关于批量http请求:http: //jonsamwell.com/batching-http-requests-in-angular/

需要一些澄清 – 你是否试图在客户端运行这个? 看起来这是在服务器端的nodejs程序中运行。 如果是这样,你是不是把这个逻辑推到客户端,并用Ajax处理。 我相信浏览器能够更好地处理多个http请求响应。

既然你没有发布关于你的csgoMarket.getSinglePrice函数的很多信息,我写了一个使用返回一个承诺。 这将允许你使用你应该阅读的Q.all,因为它会真正帮助你的情况。

我创build了一个内部和外部循环数组来保存我们的承诺。 这个代码是完全没有经过testing,因为你没有提起小提琴。

 var getPrice = function(theData) { var wep = theData.weapon; var completed = 0; var promises_outer = [] //array to hold the arrays of our promises for (var i = 0; i < theData.skins.length; i++) { var currSkin = theData.skins[i]; theData.skinData[currSkin] = {}; var promises_inner = [] // an array to hold our promises for (var k = 0; k < wears.length; k++) { //wears.length is referenced to below but not decalared anywhere in the function. It's either global or this function sits somewhere where it has access to it promises_inner.push(csgomarket.getSinglePrice(wep, currSkin, wears[k], false)) } promises_outer.push(promises_inner) } promises_outer.forEach(function(el, index){ var currSkin = theData.skins[index] theData.skinData[currSkin] = {} Q.all(el).then(function(data){ //data is an array of results in the order you made the calls if(data){ theData.skinData[data.skin][data.wear] = data } }) }) } var csgomarket = {} csgomarket.getSinglePrice = function(wep, currSkin, wears, someBoolean){ return Q.promise(function (resolve, reject){ //do your request or whatever you do var result = true var data = { skin : "cool one", wear : "obviously" } var error = new Error('some error that would be generated') if(result){ resolve(data) } else { reject(error) } }) }