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

时间:2015-08-01 09:18:11

标签: javascript node.js promise q

我尝试使用q以及async执行此操作,但似乎无法使其正常工作。尝试过后,我尝试了自己的方式。我不认为这会起作用,但我想我会尝试一下。我很困惑,因为在某种意义上回调中有一个回调。这是我想要做的功能:

>>> ind=[0]+[i for i,j in enumerate(input_list,1) if j.isdigit()]
>>> [input_list[i:j] for i,j in zip(ind,ind[1:])]
[['string', 'string', '1'], ['string', '2'], ['string', 'string', '3'], ['string', '5']]

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

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

由于每次调用csgomarket.getSinglePrice(wep, currSkin, wears[k], false, function(err, data) { }); 都会发送一个GET请求,因此回复需要一些时间。任何建议或帮助将不胜感激!

4 个答案:

答案 0 :(得分:2)

首先csgomarket.getSinglePrice()需要被宣传。这是一个调用csgomarket.getSinglePrice()并返回Q承诺的适配器函数。

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()现在返回一个promise时,必须按如下方式使用:

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

答案 1 :(得分:0)

你的方式非常复杂。

我认为最好的方法是对所有价格做1次请求。现在,您可以针对每个价格提出要求。 如果您有一个包含请求所需数据的列表(数组),则返回值应该是包含价格的列表。

如果无法实现上述方法,您可以阅读有关批量处理http请求的更多信息:http://jonsamwell.com/batching-http-requests-in-angular/

答案 2 :(得分:0)

需要澄清一下 - 您是否尝试在客户端运行此操作?看起来这是在服务器端的nodejs程序中运行。如果是这样,您是不是宁愿将此逻辑推送到客户端并使用Ajax处理。我相信浏览器可以更好地处理多个http请求响应。

答案 3 :(得分:0)

由于您没有发布有关csgoMarket.getSinglePrice函数的大量信息,因此我编写了一个使用返回promise的函数。这将允许您使用Q.all,您应该阅读它,因为它会对您的情况有所帮助。

我已经创建了一个内部和外部循环数组来保持我们的承诺。这段代码完全没有经过测试,因为你没有小提琴。

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