AngularJS从一个服务广播,不触发对第二个服务的调用

AngularJS从一个服务广播,不触发对第二个服务的调用,angularjs,youtube-api,Angularjs,Youtube Api,我已经定义了两个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 = doc

我已经定义了两个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;
}]);
function ReceiverCtrl($scope,$rootScope,$routeParams,ytplayer,ytdataapi) {
  $scope.$on('loadedApi',function () {
    ytplayer.videoId='voNEBqRZmBc';
    ytplayer.loadPlayer();
  });
}
      $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
        });
      });
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();
  });
}
(还要注意,我的播放器服务的“setPlayerId”函数是由自定义指令调用的……但这对于我的问题并不重要)

所以,问题来了。我需要确保在设置视频id和创建播放器之前加载播放器API代码,这就是为什么我让它广播“loadedApi”消息的原因。如果我在我的控制器中传递一个硬编码的视频id,这非常有效,如下所示:

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;
}]);
function ReceiverCtrl($scope,$rootScope,$routeParams,ytplayer,ytdataapi) {
  $scope.$on('loadedApi',function () {
    ytplayer.videoId='voNEBqRZmBc';
    ytplayer.loadPlayer();
  });
}
      $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
        });
      });
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();
  });
}
但是,在使用数据API服务进行API调用之前,无法确定我的视频ID,因此我还必须确保调用的结果已返回。这就是我遇到问题的地方。。。如果我这样做:

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;
}]);
function ReceiverCtrl($scope,$rootScope,$routeParams,ytplayer,ytdataapi) {
  $scope.$on('loadedApi',function () {
    ytplayer.videoId='voNEBqRZmBc';
    ytplayer.loadPlayer();
  });
}
      $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
        });
      });
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();
  });
}
$scope.$on('loadedApi',函数(){
ytdataapi.search(“广告狂人”,{'topicId':$routeParams.topicId,
“类型”:“视频”,
'order':'viewCount'})

.success(函数(apiresults){/解决了这个问题;我必须调用$scope.$apply(),如下所示:

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;
}]);
function ReceiverCtrl($scope,$rootScope,$routeParams,ytplayer,ytdataapi) {
  $scope.$on('loadedApi',function () {
    ytplayer.videoId='voNEBqRZmBc';
    ytplayer.loadPlayer();
  });
}
      $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
        });
      });
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();
  });
}

但是,有没有人能解释一下为什么这样做?$scope.$digest()也可以……但是我认为这些方法只在需要更新绑定时使用,因为Angular不知道一些javascript代码。我在这里找到的嵌套是这样做的(我不认为应该,因为我的ytdataapi服务使用$http)?

看起来搜索功能没有对作用域进行任何更改,它只是触发了一个http请求。这很奇怪。您好,感谢您与我们分享您的答案!但我不明白的一件事是如何将you tube播放器绑定到DOM元素。此外,如何在不加载插件的情况下一个接一个地加载多个不同的视频还有一个github repo是这个问题的一种演变:……它包括用于将播放器绑定到DOM元素的盎格鲁指令。我还没有考虑加载多个视频,但这应该不难……也许我会将其添加到repo代码中。