我已经定义了两个AngularJS服务…一个用于YouTube播放器API,另一个用于YouTube iFrame数据API.它们看起来像这样:
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; }]);
(另请注意,我的播放器服务的’setPlayerId’功能是由自定义指令调用的……但这对我的问题并不重要).
所以,这是问题所在.在设置视频ID并创建播放器之前,我需要确保加载播放器API代码,这就是我播放’loadedApi’消息的原因.如果我在我的控制器中传递一个硬编码的视频ID,这个效果很好,如下所示:
function ReceiverCtrl($scope,$rootScope,$routeParams,ytplayer,ytdataapi) { $scope.$on('loadedApi',function () { ytplayer.videoId='voNEBqRZmBc'; ytplayer.loadplayer(); }); }
但是,在我使用数据api服务进行API调用之前,我的视频ID将无法确定,因此我还必须确保该调用的结果已经恢复.这就是我遇到问题的地方……如果我做这样的事情:
$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 }); });
然后,由于某种原因,与数据服务的交互永远不会发生.我知道数据服务工作正常,因为当我从$on语句取消嵌套时,它返回api结果.但有时延迟使得结果不能足够快地返回到在播放器服务中使用它们.在接收到播放器API准备好的消息后,我仍然可以做什么来进行数据搜索,但仍然将两个服务保持为两个独立的服务(因为其他控制器只使用一个或另一个,所以我不想要他们在服务水平上相互依赖)?
解决方法
弄清楚了;我不得不调用$scope.$apply(),如下所示:
function ReceiverCtrl($scope,function () { ytdataapi.search("",'maxResults':1,'order':'viewCount'}).success(function(apiresults) { ytplayer.videoId=apiresults.items[0].id.videoId; ytplayer.loadplayer(); }); $scope.$apply(); }); }
有没有人可以解释为什么这样有效? $scope.$digest()也有效…但我认为这些方法仅在你需要更新绑定时使用,因为Angular不知道一些javascript代码.是我在这里做的那样的嵌套(我不认为它应该,因为我的ytdataapi服务使用$http)?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。