Search code examples
ajaxangularjsservicejsonp

Should I create a .factory in order to share a variable's value to two ajax requests?


Using angularjs I have made two ajax json requests, the first request is retrieving channel's online / offline status and the second ajax json request is for the channel's info (logo, name, status etc).

I assigned the variable signal to 'data.stream' which is the online / offline status for channels to share signal between json requests. In Google Developer console I am receiving a value of null. I did some research here http://www.ng-newsletter.com/posts/beginner2expert-services.html and found that using a service might be a solution. I followed the directions but I'm still unable to get the scope between json request to recognize signal.

I read that rootscope could be used but it's not recommend, not sure how true that is because a novice using angular but I want start my angular journey by applying best practices.

Recap: Using Angular Ajax to make a jsonp request to twitch api, I am make two requests one to retrieve the online / offline status of channels in my streamers array, and the other ajax json request is to retrieve the channel's info, and I need the scope of the variable signal which has been assigned the value data.stream to be seen between ajax jsonp requests. Please let me know if this is a logical approach or if I'm "going around the world again".

Here is a plunker: plnkr.co/edit/6sb39NktX7CwfnQFxNNX

// creating a service for signal ?    
app.factory('signal', function() {
                var signal = {};

                return signal;
            })

            // declaring my TwitchController and dependencies 
            app.controller('TwitchController', ['$scope', '$http', 'signal', function($scope, $http, signal) {
                // streamers array with array of channels
                var streamers = ["freecodecamp", "storbeck", "terakilobyte", "habathcx", "RobotCaleb", "thomasballinger", "noobs2ninjas", "beohoff", "medrybw"];

                $scope.imgs;
                $scope.signal = signal;

                var self = this;

                //empty array
                self.info = [];
                for (var i = 0; i < streamers.length; i++) {
                    var url = "https://api.twitch.tv/kraken/channels/";
                    var streamUrl = "https://api.twitch.tv/kraken/streams/";
                    var callback = "/?callback=JSON_CALLBACK";
                    //json ajax request for channels online and offline status
                    $http.jsonp(streamUrl + streamers[i] + callback).success(function(data) {

                        //provides status of shows online and offline
                        signal = data.stream;
                        console.log(signal)

                    });
                    // json ajax request for channels and channel's info
                    $http.jsonp(url + streamers[i] + callback).success(function(data) {
                        // if channel does not have a logo image, this jpg will be the placeholder 
                // if statement test channel status (online or offline)
                        if (!signal) {
                            signal = "offline";
                        } else if (signal) {
                            signal = 'online';
                        }

                        // pushing retreive data from twitch.tv into array self.info 
                        self.info.push(data);

                    });

Solution

  • Your issue here is async call to $http. You need to use $http.then and chain the promises. You do not need a factory for this instance but it is best practice to have one that just returns your info object. I didn't know exactly the format you wanted so I created one. Here is the plunker: http://plnkr.co/edit/ecwk0vGMJCvkqCbZa7Cw?p=preview

    var app = angular.module('Twitch', []);
    
    // declaring my TwitchController and dependencies 
       app.controller('TwitchController', ['$scope', '$http', function($scope, $http) {
    
        // streamers array with array of channels
        var streamers = ['freecodecamp', 'storbeck','terakilobyte', 'habathcx', 'RobotCaleb', 'thomasballinger', 'noobs2ninjas', 'beohoff', 'medrybw' ];
    
        //empty array
        $scope.info = [];
    
        var url = 'https://api.twitch.tv/kraken/channels/';
        var streamUrl = 'https://api.twitch.tv/kraken/streams/';
        var callback = '/?callback=JSON_CALLBACK';
    
        angular.forEach(streamers, function(stream) {
          //json ajax request for channels online and offline status
          $http.jsonp(streamUrl + stream + callback).then(function (data) {
            //provides status of shows online and offline
    
            // json ajax request for channels and channel's info
            $http.jsonp(url + stream + callback).then(function (channelData) {
              // pushing retrieve data from twitch.tv into array self.info
               $scope.info.push(
                {
                  url: url + stream,
                  stream: stream,
                  status: !data.stream ? 'offline' : 'online', // ternary statement test channel status (online or offline)
                  logo: channelData.data.logo ?  channelData.data.logo : 'placeholderlogo.jpg' // if channel does not have a logo image, this jpg will be the placeholder
                }
              );
            });
          });
        });
      }]);