0

I'm creating an angular directive for realtime chart displaying here is the code which returns everything including link:function() { } inside directive.

Here is the code for static directive which works perfectly

angular.module('app').directive("flotChartRealtime", [
    function() {
        return {
            restrict: "AE",
            link: function(scope, ele) {
                var realTimedata,
                    realTimedata2,
                    totalPoints,
                    getSeriesObj,
                    getRandomData,
                    getRandomData2,
                    updateInterval,
                    plot,
                    update;
                return realTimedata = [],
                    realTimedata2 = [],
                    totalPoints = 100,
                    getSeriesObj = function() {
                        return [
                            {
                                data: getRandomData(),
                                lines: {
                                    show: true,
                                    lineWidth: 1,
                                    fill: true,
                                    fillColor: {
                                        colors: [
                                            {
                                                opacity: 0
                                            }, {
                                                opacity: 1
                                            }
                                        ]
                                    },
                                    steps: false
                                },
                                shadowSize: 0
                            }, {
                                data: getRandomData2(),
                                lines: {
                                    lineWidth: 0,
                                    fill: true,
                                    fillColor: {
                                        colors: [
                                            {
                                                opacity: .5
                                            }, {
                                                opacity: 1
                                            }
                                        ]
                                    },
                                    steps: false
                                },
                                shadowSize: 0
                            }
                        ];
                    },
                    getRandomData = function() {
                        if (realTimedata.length > 0)
                            realTimedata = realTimedata.slice(1);

                        // Do a random walk
                        //console.log(realTimedata);
                        while (realTimedata.length < totalPoints) {

                            var prev = realTimedata.length > 0 ? realTimedata[realTimedata.length - 1] : 50,
                                y = prev + Math.random() * 10 - 5;

                            if (y < 0) {
                                y = 0;
                            } else if (y > 100) {
                                y = 100;
                            }
                            realTimedata.push(y);
                        }

                        // Zip the generated y values with the x values

                        var res = [];
                        for (var i = 0; i < realTimedata.length; ++i) {
                            res.push([i, realTimedata[i]]);
                        }

                        return res;
                    },
                    getRandomData2 = function() {
                        if (realTimedata2.length > 0)
                            realTimedata2 = realTimedata2.slice(1);

                        // Do a random walk

                        while (realTimedata2.length < totalPoints) {

                            var prev = realTimedata2.length > 0 ? realTimedata[realTimedata2.length] : 50,
                                y = prev - 25;

                            if (y < 0) {
                                y = 0;
                            } else if (y > 100) {
                                y = 100;
                            }
                            realTimedata2.push(y);
                        }


                        var res = [];
                        for (var i = 0; i < realTimedata2.length; ++i) {
                            res.push([i, realTimedata2[i]]);
                        }

                        return res;
                    },

                    // Set up the control widget
                    updateInterval = 500,
                    plot = $.plot(ele[0], getSeriesObj(), {
                        yaxis: {
                            color: '#f3f3f3',
                            min: 0,
                            max: 100,
                            tickFormatter: function(val, axis) {
                                return "";
                            }
                        },
                        xaxis: {
                            color: '#f3f3f3',
                            min: 0,
                            max: 100,
                            tickFormatter: function(val, axis) {
                                return "";
                            }
                        },
                        grid: {
                            hoverable: true,
                            clickable: false,
                            borderWidth: 0,
                            aboveData: false
                        },
                        colors: ['#eee', scope.settings.color.themeprimary],
                    }),
                    update = function() {
                        plot.setData(getSeriesObj()); // getting .data filled here perfectly
                        plot.draw();
                        setTimeout(update, updateInterval);
                    },
                    update();
            }
        };
    }
]);

My code with HTTP request which doesn't work

 getSeriesObj = function () {
     return [{
         data: getRandomData(function(res) {
             console.log(res) // getting array result here from http call but not returning to data:
             return res; 
         }),
         lines: {
             show: true,
             lineWidth: 1,
             fill: true,
             fillColor: {
                 colors: [{
                     opacity: 0
                 }, {
                     opacity: 1
                 }]
             },
             steps: false
         },
         shadowSize: 0
     }, {
         data: getRandomData2(function (res) {
             return res;
         }),
         lines: {
             lineWidth: 0,
             fill: true,
             fillColor: {
                 colors: [{
                     opacity: .5
                 }, {
                     opacity: 1
                 }]
             },
             steps: false
         },
         shadowSize: 0
     }];
 },
 getRandomData = function (callback) {
     var authToken = window.localStorage.getItem('token');
     var url = $rootScope.apiPath + 'Elasticsearch/countget?token=' + authToken;
     var res = [];
     $http.get(url).then(function (result) {
         realTimedata = result.data;
         if (realTimedata.length > 0)
         //result = [10,22,33,11,32,88,77,66,21,90,92,98,99.9,88.8,76,66,56,88];
         for (var i = 0; i < realTimedata.length; ++i) {
             var y = realTimedata[i] + Math.random() * 10 - 5;
             if (y < 0) {
                 y = 0;
             } else if (y > 100) {
                 y = 100;
             }
             res.push([i, y]);
         }
         callback(res);
     });
 },

Problem:

When i try following code:

update = function () {
    //console.log(getSeriesObj());
    plot.setData(getSeriesObj()); // .data property gets undefined
    plot.draw();
    setTimeout(update, updateInterval);
}

function getSeriesObj() return array of object which return data property to undefined what can be the reason?

how can i resolve this?

Note: This is far different from this question.

Community
  • 1
  • 1
Dhaval Marthak
  • 17,246
  • 6
  • 46
  • 68
  • is `getRandomData2` same as `getRandomData ` ? because if so then `getRandomData2` might return nothing because of the async task so `data` is undefined – Hacketo Sep 10 '15 at 07:40
  • possible duplicate of [How to return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – Hacketo Sep 10 '15 at 07:41
  • `data: getRandomData2(function (res) {return res;})` this execute `getRandomData2`, what does return `getRandomData2` ? `undefined` . Your issue is the same as defined in the post I linked. You are not able to return the response from the async call – Hacketo Sep 10 '15 at 07:46
  • @Hacketo Both are same right now just! – Dhaval Marthak Sep 10 '15 at 07:47
  • @Hacketo I'm getting result where i call `data: getRandomData2(function (res) {return res;})` where `res` is an array but it's not getting populated inside `update()` at the bottom. – Dhaval Marthak Sep 10 '15 at 07:50
  • `res` is an array, but what is `data` then ? `undefined`, the problem you asked about – Hacketo Sep 10 '15 at 07:52
  • @Hacketo `res = [[1,2],[2,3].......]` i get this response inside `res`! and this `res` is returned to `data` property! but i get undefined in `update()` – Dhaval Marthak Sep 10 '15 at 07:53
  • so what is the problem ? `res` is not returned to `data`, `data` is undefined, this is not a function – Hacketo Sep 10 '15 at 07:53
  • If you want to see it , just call `getRandomData2(function (res) {return res;})` in js console, you will see that it return nothing, so assigning the return of that function to `data` is your problem – Hacketo Sep 10 '15 at 08:01
  • @Hacketo I did it, it returns me the result in `res`! – Dhaval Marthak Sep 10 '15 at 09:04
  • the function call itself return nothing so you assign nothing to `data`, as opposite of the first `data` value where you assign a function to `data`. If you can't understand that, the post linked is the solution – Hacketo Sep 10 '15 at 09:21
  • BTW after your last edit, `data: getRandomData(res) { return res; }` is not valid javascript – Hacketo Sep 10 '15 at 09:28
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/89253/discussion-between-dhaval-marthak-and-hacketo). – Dhaval Marthak Sep 10 '15 at 09:31
  • I guess you are not returning anything in the Async call... that might be the reason. – Ashish Panchal Sep 10 '15 at 10:15

1 Answers1

2

When do this

data: getRandomData(function(res) {
    return res; 
});

You assign the rValue of getRandomData to data.

As stated in your post, getRandomData now has no return statement, so return undefined.

The main problem here is that you expect that plot.setData(getSeriesObj()); work synchronously

Steps

  1. get the data to fill plot
  2. set the data to the plot
  3. draw it
  4. update the values again

Now as the http request work async you cannot expect to retrieve a value from getSeriesObj(). You have to think that getSeriesObj work now async so you can only work with callback that will be fired when the resource is ready to be used

so the update method become

update = function () {
    var updateTime = +new Date;
    getSeriesObj(function(res){ // execute that stuff when ready
        plot.setData(res);
        plot.draw();
        setTimeout(update, Math.max(10, updateInterval - (+new Date - updateTime)) );
    });
}

and getSeriesObj

getSeriesObj = function (callback) {
    getRandomData(function(res) {
        getRandomData2(function(res2){
            var data = [{
                data: res,
                lines: {
                    show: true,
                    lineWidth: 1,
                    fill: true,
                    fillColor: {
                        colors: [{
                            opacity: 0
                        }, {
                            opacity: 1
                        }]
                    },
                    steps: false
                },
                shadowSize: 0
            }, {
                data: res2,
                lines: {
                    lineWidth: 0,
                    fill: true,
                    fillColor: {
                        colors: [{
                            opacity: .5
                        }, {
                            opacity: 1
                        }]
                    },
                    steps: false
                },
                shadowSize: 0
            }];
            callback(data); // now the ressource obj is now ready to be used
        });
    });
}
Hacketo
  • 4,978
  • 4
  • 19
  • 34