如何在for循环之后返回单个promise(在每次迭代时产生一个promise)是否完成?

Leo*_*ban 6 javascript for-loop promise angularjs angular-promise

我的承诺返回代码有问题,我有一个getTagQuotes包含for循环的函数,它可以使多个调用API将数据返回到数组中.

我的代码如何从下面开始:

// If there are tags, then wait for promise here:
if (tags.length > 0) {

    // Setting promise var to getTagQuotes:
    var promise = getTagQuotes(tags).then(function() {
        console.log('promise =',promise);

        // This array should contain 1-3 tags:
        console.log('tweetArrayObjsContainer =',tweetArrayObjsContainer);

        // Loop through to push array objects into chartObj:
        for (var i=0; i<tweetArrayObjsContainer.length; i++) {
            chartObj.chartData.push(tweetArrayObjsContainer[i]);
        }

        // Finally draw the chart:
        chartDirective = ScopeFactory.getScope('chart');
        chartDirective.nvd3.drawChart(chartObj.chartData);
    });
}
Run Code Online (Sandbox Code Playgroud)

我的getTagQuotes函数带有promise返回:

function getTagQuotes(tags) {
    var deferred = $q.defer(); // setting the defer
    var url      = 'app/api/social/twitter/volume/';

    // My for loop, which only returns ONCE, even if there are 3 tags
    for (var i=0; i<tags.length; i++) {
        var loopStep = i;
        rawTagData   = [];

        // The return statement
        return GetTweetVolFactory.returnTweetVol(url+tags[i].term_id)
            .success(function(data, status, headers, config) {
                rawTagData.push(data);

                // One the last loop, call formatTagData
                // which fills the tweetArrayObjsContainer Array
                if (loopStep === (rawTagData.length - 1)) {
                    formatTagData(rawTagData);
                    deferred.resolve();
                    return deferred.promise;
                }
            });
    }

    function formatTagData(rawData) {

        for (var i=0; i<rawData.length; i++) {
            var data_array = [];
            var loopNum = i;

            for (var j=0; j<rawData[loopNum].frequency_counts.length; j++) {
                var data_obj = {};
                data_obj.x = rawData[loopNum].frequency_counts[j].start_epoch;
                data_obj.y = rawData[loopNum].frequency_counts[j].tweets;
                data_array.push(data_obj);
            }

            var tweetArrayObj = {
                "key" : "Quantity"+(loopNum+1), "type" : "area", "yAxis" : 1, "values" : data_array
            };

            tweetArrayObjsContainer.push(tweetArrayObj);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

注意这一行

return GetTweetVolFactory.returnTweetVol(url+tags[i].term_id)
Run Code Online (Sandbox Code Playgroud)

它在我的for循环中:

for (var i=0; i<tags.length; i++)
Run Code Online (Sandbox Code Playgroud)

如果我只需要循环一次,一切都很好.但是,只要有另一个标签(最多3个),它仍然只返回第一个循环/数据.它不会等到for循环完成.然后回复承诺.所以我tweetArrayObjsContainer总是只有第一个标签.

Ben*_*lde 2

三个问题:

  1. 您没有从该getTagQuotes方法返回延迟的承诺。
  2. 您正在查看i是否已完成循环,并且i == (tags.length - 1)在调用第一个成功之前 for 循环已经完成 ( ) 。
  3. return在循环的第一次迭代中进行了调用,因此您甚至没有到达第二项。

这是更正后的代码(尚未测试)

function getTagQuotes(tags) {
    var deferred = $q.defer(); // setting the defer
    var url      = 'app/api/social/twitter/volume/';
    var tagsComplete = 0;

    for (var i=0; i<tags.length; i++) {
        rawTagData   = [];
        GetTweetVolFactory.returnTweetVol(url+tags[i].term_id)
            .success(function(data, status, headers, config) {
                rawTagData.push(data);
                tagsComplete++;

                if (tagsComplete === tags.length) {
                    formatTagData(rawTagData);
                    deferred.resolve();
                }
            });
    }

    return deferred.promise;
}
Run Code Online (Sandbox Code Playgroud)