AngularJS broadcasts from one service without calling a second service call

I defined two AngularJS services ... one for the YouTube Player APIs and the other for the YouTube iFrame Data APIs. They look like this:

angular.module('myApp.services',[]).run(function() { var tag = document.createElement('script'); tag.src = "//www.youtube.com/iframe_api"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); }) .factory('YtPlayerApi', ['$window', '$rootScope', function ($window, $rootScope) { var ytplayer = {"playerId":null, "playerObj":null, "videoId":null, "height":390, "width":640}; $window.onYouTubeIframeAPIReady = function () { $rootScope.$broadcast('loadedApi'); }; ytplayer.setPlayerId = function(elemId) { this.playerId=elemId; }; ytplayer.loadPlayer = function () { this.playerObj = new YT.Player(this.playerId, { height: this.height, width: this.width, videoId: this.videoId }); }; return ytplayer; }]) .factory('YtDataApi', ['appConfig','$http', function(cfg,$http){ var _params = { key: cfg.youtubeKey }; var api="https://www.googleapis.com/youtube/v3/"; var yt_resource = {"api":api}; yt_resource.search = function(query, parameters) { var config = { params: angular.extend(angular.copy(_params), {maxResults: 10, part: "snippet"}, parameters) }; return $http.get(api + "search?q=" + query, config); }; return yt_resource; }]); 

(also note that the setPlayerId function of my player service is called by the user directive ... but this is not important for my question).

So here is the problem. I need to make sure that the Player API code is loaded before I set the video ID and create the player, so I passed the message "loadedApi" to it. And this works fine if I then pass a hard-coded video identifier in my controller, for example:

 function ReceiverCtrl($scope,$rootScope,$routeParams,ytplayer,ytdataapi) { $scope.$on('loadedApi',function () { ytplayer.videoId='voNEBqRZmBc'; ytplayer.loadPlayer(); }); } 

However, my video IDs will not be determined until I call the API using the data api service, so I also need to make sure that the results of this call are returned. And then where I ran into problems ... if I do something like this:

  $scope.$on('loadedApi',function () { ytdataapi.search("Mad Men", {'topicId':$routeParams.topicId, 'type':'video', 'order':'viewCount'}) .success(function(apiresults) { // <-- this never gets triggered console.log(apiresults); // <-- likewise, this obviously doesn't either }); }); 

Then the interaction with the data service never happens for some reason. I know that the data service works very well, because when I disconnect it from the $ on statement, it returns api results. But sometimes latency does this so that the results do not return fast enough to be used in the player’s service. Any thoughts on what I can do to search the data after receiving a message that the player’s API is ready but still save the two services as two separate services (because the other controllers use only one or the other, therefore I do not want they depend on each other at the service level)?

+6
source share
1 answer

Figured it out; I had to call $ scope. $ Apply (), for example:

 function ReceiverCtrl($scope,$rootScope,$routeParams,ytplayer,ytdataapi) { $scope.$on('loadedApi',function () { ytdataapi.search("",{'topicId':$routeParams.topicId,'type':'video','maxResults':1,'order':'viewCount'}).success(function(apiresults) { ytplayer.videoId=apiresults.items[0].id.videoId; ytplayer.loadPlayer(); }); $scope.$apply(); }); } 

Is there anyone who could shed light on why this works? $ scope. $ digest () also works ... but I thought that these methods were only used when you need to update bindings due to some javascript code that Angular is not aware of. Is this the nesting I am doing here (I would not have thought it was necessary since my ytdataapi service uses $ http)?

+2
source

Source: https://habr.com/ru/post/951915/


All Articles