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) {
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)?