0

I'm making http- requests to get some information and show them in a bar chart. It is not working unless I include alert(" ")

Almost everything works fine, but without alert() the chart doesn't work. How can I solve this problem?

app.controller('StatisticsCtrl', function ($scope, GitHubService) {


    // funktioniert - Test
    var getFollowedTmp = 0;
    var getFollowersTmp = 0;
    var getStarredTmp = 0;//Favoriten

    GitHubService.getFollowed(function (data) {
        getFollowedTmp = data.length;
    });
    GitHubService.getFollowers(function (data) {
        getFollowersTmp = data.length;
    });
    GitHubService.getStarred(function (data) {
        getStarredTmp = data.length;
    });


    alert("");
    var ctx = document.getElementById("profChart");
    var myChart = new Chart(ctx, {
        type: 'bar',
        data: {
            labels: ["Followers", "Following", "Starred"],
            datasets: [{
                label: 'Quantity',//Anzahl
                backgroundColor: "rgba(0,51,48,0.2)",
                borderColor: "rgba(0,51,48,0.2)",
                borderWidth: 1,             
                data: [getFollowersTmp, getFollowedTmp, getStarredTmp]
            }]
        },

        options: {
                scales: {
                    yAxes: [{
                        ticks: {
                            beginAtZero:true
                        }
                    }]
                }
            }
        });

});
Adam Konieska
  • 2,805
  • 3
  • 14
  • 27

3 Answers3

3

methods in GitHubService are async. When you call alert(""), you're blocking execution from going to the next line and thus giving the git hub service time to run and return.

Here's an example of chaning with Jquery. Other js frameworks, will have similar concepts.

var task1  = $.getJSON("http://resourceUri");
var task2  = $.getJSON("http://resourceUri2");

$.when(task1, task2).done(function(task1Response, task2Response){
   var task1Result = task1Response[0];
   var task2Result = task2Response[0];

   //Do something with the data. Charting?
});
dfdsfdsfsdf
  • 653
  • 3
  • 7
  • so what i need to do? – thenewOne1234567890 May 11 '16 at 17:22
  • Along KMC's answer I would wrap your service calls in a promise and then on success bind the items to the UI – rlcrews May 11 '16 at 17:23
  • so with rlcrews's comment, can you see what's returned when you invoke GitHubService.getStarred()? if it's a promise object (ref jquery api), you can do function chaining. For ex) GitHubService.getStarred().done(function(){ //do something}) – dfdsfdsfsdf May 11 '16 at 17:25
  • oh, is GitHubService you're own abstraction or part of GitHub? – dfdsfdsfsdf May 11 '16 at 17:28
  • if you don't want to invest time in learning the concept of "promise" and deferred objects, you can look at "riscarrott" solution at the bottom. – dfdsfdsfsdf May 11 '16 at 17:37
1

The reason it doesn't work without the alert is because the GitHubService calls are async so the data isn't there by the time you render your chart.

The reason it works with alert is because alert pauses the execution (which to be fair is a little magic) so by the time you dismiss the alert the requests have completed.

You'll need to wait for the three GitHub service calls to complete before rendering the chart.

This could be achieved like this:

function tryRender() {
    if (getFollowedTmp && getFollowersTmp && getStarredTmp) {
         var myChart = new Chart(...);
    }
}

GitHubService.getFollowed(function (data) {
    getFollowedTmp = data.length;
    tryRender();
});
GitHubService.getFollowers(function (data) {
    getFollowersTmp = data.length;
    tryRender();
});
GitHubService.getStarred(function (data) {
    getStarredTmp = data.length;
    tryRender();
});

However that isn't overly elegant. If your GitHubService calls return promises (Many ajax libraries do) you could do:

Promise.all([
    GitHubService.getFollowed(),
    GitHubService.getFollowers(),
    GitHubService.getStarred()
]).then(function(result) {
    var getFollowedTmp = result[0].length;   
    var getFollowersTmp = result[1].length;
    var getStarredTmp = result[2].length;
    var myChart = new Chart(...);
});
Richard Scarrott
  • 6,638
  • 1
  • 35
  • 46
0

One of the usual reasons that "removing blocking calls breaks my code" is because the blocking call gives time for the browser to load resources.

In your case I believe that getFollowersTmp, getFollowedTmp, getStarredTmp are not initialized in time.

One of the ways to solve it is to use AngularJS's $q to make sure all dependencies are loaded before continuing.

Derek 朕會功夫
  • 92,235
  • 44
  • 185
  • 247