1

I have an array of tags which may contain up to 3 items.

Next I pass tags into my getTagQuotes function and am trying to set a promise variable to it. Right now I'm getting promise is undefined.

enter image description here

// If there are tags, the wait for promise here:
if (tags.length > 0) {
    var promise = getTagQuotes(tags).then(function() {
        console.log('promise =',promise);

        for (var i=0; i<tweetArrayObjsContainer.length; i++) {
            chartObj.chartData.push(tweetArrayObjsContainer[i]);
        }

        chartDirective = ScopeFactory.getScope('chart');
        chartDirective.nvd3.drawChart(chartObj.chartData);
    });
}
else {
    chartDirective = ScopeFactory.getScope('chart');
    chartDirective.nvd3.drawChart(chartObj.chartData);
}

^ The goal above is to make sure that arrays in tweetArrayObjsContainer have been filled and pushed into chartObj.chartData before I draw my nvd3 chart.

Below is my getTagQuotes function which does another loop through the tags (up to 3) and calls another service GetTweetVolFactory.returnTweetVol which makes the actual API call to retrieve data.

I have code which checks if the we're on the final loop step, then calls the formatTagData function.

Inside formatTagData is where I fill the tweetArrayObjsContainer.

// Check for and GET tag data:
////////////////////////////////////////////////////////////////////
function getTagQuotes(tags) {
    console.log('getTagQuotes called with',tags);
    var deferred   = $q.defer(); // <- setting $q.defer here
    var url        = 'app/api/social/twitter/volume/';

    for (var i=0; i<tags.length; i++) {
        var loopStep = i;
        rawTagData   = [];

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

                if (loopStep === (rawTagData.length - 1)) {
                    // formatTagData fills the tweetArrayObjsContainer with data:
                    formatTagData(rawTagData);
                    deferred.resolve(); // <-- last step, so resolve
                    return deferred.promise;
                }
            })
            .error(function(data, status) {
                return 'error in returning tweet data';
            });
    }

    function formatTagData(rawData) {
        tweetArrayObjsContainer = [];

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

            _(rawData[i].frequency_counts).reverse().value();

            for (var j=0; j<rawData[loopNum].frequency_counts.length; j++) {
                var data_obj = {};
                rawData[loopNum].frequency_counts[j].start_epoch = addZeroes(rawData[loopNum].frequency_counts[j].start_epoch);
                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"+(i+1),
                "type"   : "area",
                "yAxis"  : 1,
                "color"  : tagColorArray[i],
                "values" : data_array
            };

            tweetArrayObjsContainer.push(tweetArrayObj);
        }
    }
}
Leon Gaban
  • 36,509
  • 115
  • 332
  • 529
  • 2
    You're missing the point *entirely* of promises! – Jamiec Oct 07 '15 at 15:34
  • In your `getTagQuotes` function you are not returning any promise. For this reason is undefined when you check it. It's better if you read some documentation about "promises", for example [MDN Promise page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). – Andrea Oct 07 '15 at 15:36
  • @jamiec Promises tell a function to wait till something is returned before continuing along a chain, or just continuing correct? – Leon Gaban Oct 07 '15 at 15:59
  • No, not at all. there is no waiting involved. Promises provide a method to supply a callback which should be actioned when the asynchronous action completes. – Jamiec Oct 07 '15 at 16:12

2 Answers2

2

Your getTagQuotes function should return a promise with the $q service, check it out.

It should look like this:

function getTagQuotes(tags) {
    var deferred = $q.defer();

    (...)
    // When the action is finished here, call resolve:
    deferred.resolve();
    (...)

    // And in the end, return the promise
    return deferred.promise;
}

And finally, in your main code, you'll do:

var promise = getTagQuotes(tags).then(function(){
    console.log('promise =',promise);
    // Fill chartObj with tweet data arrays
    (...)
});
Fernando Pinheiro
  • 1,796
  • 2
  • 17
  • 21
  • `.promise` is a property not a function - should have no parentheses – Jamiec Oct 07 '15 at 15:41
  • I'm getting `TypeError: Cannot read property 'then' of undefined` on the `var promise = getTagQuotes(tags)` line.. will post a gist in a bit – Leon Gaban Oct 07 '15 at 15:45
  • Ah! I forgot to return `return GetTweetVolFactory.returnTweetVol` – Leon Gaban Oct 07 '15 at 16:00
  • 1
    You cannot return it. If you do so the for loop is worthless and you'll return always the first call. – Fernando Pinheiro Oct 07 '15 at 16:13
  • @FernandoPinheiro thanks! Yeah I just found that problem out... trying to figure out how to return promises while using a for loop. I found `promise.all` however it isn't working as expected, will post a new question soon. – Leon Gaban Oct 07 '15 at 16:26
  • http://stackoverflow.com/questions/32998045/how-to-return-promise-after-for-loop-is-complete I tried `all` but not sure how to write it for a for loop correctly. – Leon Gaban Oct 07 '15 at 16:51
1

This function has no return statement.

function getTagQuotes(tags)
Amy B
  • 108,202
  • 21
  • 135
  • 185