0

我正在完成我的第一个 Angular 项目(rails gem 版本 1.2.16。)并且似乎无法弄清楚如何正确使用 $q。

我有一个指令,点击时: 1. 调用一个指令函数,该函数调用工厂函数来运行 $http 请求 2. 在附加到页面的模板中使用指令函数/ $http 的响应。

指示:

d2jive.directive('getSpotifyTracks', ['spotifyFactory', '$compile', '$sce', '$q',
 function (spotifyFactory, $compile, $sce, $q) { 
  'use strict';

  var getTracks = function(artistName){
    var deferred = $q.defer();
    var spotifyTracks = spotifyFactory.getArtistTracks(artistName)
    deferred.resolve(spotifyTracks);
    return deferred.promise;
  }


  return {
    scope: {
      artistName: '@'
    },
    compile: function(tElement, tAttrs, artistName){

      return function(scope, iElement) {
        iElement.click(function(){

          var tracks = getTracks(scope.artistName);
          tracks.then(function(tracks){
            var t = '<iframe src="https://embed.spotify.com/?uri=spotify:trackset:Playlist:"' + tracks.spotifyTracks+ 'width="300" height="300" frameborder="0" allowtransparency="true"></iframe>';
            iElement.after($compile(t)(scope));
          });
        });
      }
    }
  }

}]);

工厂:

d2jive.factory('spotifyFactory', ['$http','$q', function($http, $q){

  var factory = {}

  factory.getArtistTracks = function(artistName){

    var tracks = {}

    var spotifyUrl = "http://ws.spotify.com/search/1/track.json?q=";

    var deferred = $q.defer();

    var getTracks = function(artistName){
      $http.get(spotifyUrl + encodeURIComponent(artistName))
        .success(function (data) {
          deferred.resolve(data);
        });
      return deferred.promise;
    };


    // tracks.spotifyTrakcs = getTracks(artistName);
    var spotifyTracks = getTracks(artistName);
    spotifyTracks.then(function(result){
        var trackArray = [];
        var tracks = result.tracks.slice(0,9);
        for (var track in tracks){
          grabbedTrack = tracks[track].href.slice(
            14, tracks[track].href.length);
          trackArray.push(grabbedTrack);
        }  
      tracks.spotifyTracks = trackArray;  
      console.log(tracks.spotifyTracks); 
    });

    return tracks;

  }


return factory;


}]);

HTML:

<div class="eventContainer row" ng-controller="VenueResultsCtrl">
  <div ng-repeat="event in events">
    <h4>
      {{event.displayName}} 
    </h4>
    <p>
      <a href="{{event.uri}}" target="_blank"> Buy Tickets</a>
    </p>
    <div ng-repeat="artist in event.performance">
      <button get-spotify-tracks artist-name="{{artist.displayName}}">Discover 
        {{artist.displayName}}<br> -- {{artist.billing}}</button><br><br>
      <div class='spotify'></div>
    </div>
  </div>
</div>

问题:在工厂函数返回响应之前加载模板。

我的解决方案:我在指令中创建了一个函数来调用工厂,并尝试使用 $q 在附加模板之前等待响应,但它似乎不起作用。

任何提示或线索将不胜感激,谢谢!

4

2 回答 2

1

我认为您也许可以使用与此类似的东西来使其正常工作:

d2jive.factory('spotifyFactory', function($http){
    var spotifyFactory = {

      var spotifyUrl = "http://ws.spotify.com/search/1/track.json?q=";

      getTracks: function(artstName){
         var promise = $http.get(spotifyUrl + encodeURIComponent(artistName))
                       .then(function (result){
           //this is where you modifiy the results
           var tracks = result.tracks.slice(0,9);
           for (var track in tracks){
              grabbedTrack = tracks[track]
                             .href.slice(14,tracks[track].href.length);
              trackArray.push(grabbedTrack);
           }  
           tracks.spotifyTracks = trackArray;  
           console.log(tracks.spotifyTracks);
           return tracks
         });
         return promise;
     });
     return spotifyFactory
});

然后在你的控制器/指令中你会像这样调用这个函数

spotifyFactory.getTracks(someArtist).then(function(d) {
   $scope.data = d;
});
于 2014-05-09T00:28:09.580 回答
1

几点建议:

  • $http 已经基于 $q。它返回一个承诺。所以你不需要用一个承诺包装 $http,它已经返回了一个。请参阅带有示例的文档。

  • 您的 getArtistTracks 函数将在“then”中的代码执行之前返回“tracks”,因为该代码是异步的。当您使用异步代码时,您无法return获得结果。相反,您可以:

    • 使用您计算的跟踪值调用回调
    • 或者,现在更喜欢,返回一个承诺并在以后实现它(推荐,因为它可以让你更好地理解如何使用承诺)。
于 2014-05-08T22:32:19.790 回答