2013-08-16 11 views
6

Zdefiniowałem dwie usługi AngularJS ... jedna dotyczy interfejsu API odtwarzacza YouTube, a druga interfejsu YouTube iFrame Data API. Wyglądają tak:AngularJS broadcast z jednej usługi nie wyzwala połączenia z drugą usługą

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; 
}]); 

(również pamiętać, że „setPlayerId” funkcja mojego serwisu gracz jest nazywany przez dyrektywę niestandardowego ... ale to nie jest ważne dla mojego pytania).

Oto, jaki jest problem. Muszę się upewnić, że kod odtwarzacza API został wczytany, zanim ustawię identyfikator wideo i utworzę odtwarzacz, dlatego mam nadawać komunikat "loadedApi". I to działa świetnie, gdybym wtedy w moim kontroler przejść zakodowane id wideo tak:

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

Jednak moje identyfikatory wideo nie zostanie określona, ​​aż położę wywołanie API z usługą api dane , więc TAKŻE RÓWNIEŻ muszę zapewnić, że wyniki tego połączenia powróciły. I właśnie tam napotykam problemy ... jeśli robię coś takiego:

 $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 
     }); 
     }); 

Wtedy interakcja z usługą danych nigdy nie dzieje się z jakiegoś powodu. Wiem, że usługa danych działa dobrze, ponieważ kiedy odłączyłem ją od instrukcji $ on, zwraca ona wyniki interfejsu API. Czasami jednak opóźnienie sprawia, że ​​wyniki nie wracają wystarczająco szybko, aby wykorzystać je w usłudze gracza. Wszelkie przemyślenia na temat tego, co mogę zrobić, aby wyszukiwanie danych nastąpiło po otrzymaniu wiadomości, że interfejs API odtwarzacza jest gotowy, ale nadal utrzymuje dwie usługi jako dwie osobne usługi (ponieważ inne kontrolery używają tylko jednego lub drugiego, więc nie chcę zależą od siebie nawzajem na poziomie usługi)?

Odpowiedz

2

Wyliczyłem to; Musiałem zadzwonić do $ scope. $ Apply(), tak:

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(); 
    }); 
} 

Czy jest ktoś, kto mógłby rzucić światło na to, dlaczego to działa? $ scope. $ digest() działa również ... ale myślałem, że te metody były używane tylko wtedy, gdy musisz zaktualizować wiązania z powodu jakiegoś kodu javascript, którego Angular nie zna. Czy to zagnieżdżenie, które tu robię (nie sądzę, że powinno, ponieważ moja usługa ytdataapi używa $ http)?

+0

Wygląda funkcja wyszukiwania nie wprowadza żadnych zmian zakresu, po prostu odpala żądanie http. To dziwne. – Diryboy

+0

Witam, dziękuję za podzielenie się z nami swoją odpowiedzią! Jedną z rzeczy, których nie rozumiem, jest to, jak wiążesz swojego gracza z rurką z elementem DOM. A także, w jaki sposób można załadować kilka różnych filmów jeden po drugim bez ładowania wtyczki ponownie –

+0

Oto reaktywacja github, która jest swego rodzaju ewolucją tego pytania: https://github.com/jlmcdonald/angular-youtube ... zawiera instrukcje Angluar do wiązania gracza z elementami DOM. Jeszcze nie myślałem o ładowaniu wielu filmów, ale to nie powinno być trudne ... może dodam je do kodu repo. – jlmcdonald

Powiązane problemy