2015-08-28 65 views
1

我對angular和http調用頗爲陌生。JavaScript中的承諾(angular)

然後我讀了一些關於承諾異步調用。我根本無法理解它。 所以我需要一些幫助來知道如果即使走向正確的方向。

我正在爲使用YouTube API v3編寫獲取Videoes的API以及有關它們的詳細信息(視圖等)。

但是我似乎得到一個錯誤,因爲我的數組一直是空的。

/*var promises = [];*/ // PROMISE 
       var videometrics; 
       var videodetails = []; 
       var deferred = $q.defer(); 

       $http.get('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=' + playlistId + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA') 
        .success(function (response) { 

         for (var i = 0; i < response.items.length; i++) { 
          var video = { 
           id: response.items[i].snippet.resourceId.videoId, 
           title: response.items[i].snippet.title 
          }; 
          $scope.video.push(video) 


         } 
         /*console.log($scope.video) 
         var promises = [];*/ 
         for (i = 0; i < $scope.video.length; i++) { 
          /*console.log("looping") 
          console.log($scope.video) 
          console.log("Vi henter fra id:") 
          console.log($scope.video[i].id)*/ 
          $http.get('https://www.googleapis.com/youtube/v3/videos?part=statistics&id=' + $scope.video[i].id + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA') 
           .success(function (responsevideo) { 
            /*console.log($scope.video[i].id);*/ 

            //        console.log("we are in the metric loop") 
            //        console.log($scope.video[i].id) 
            //        console.log($scope.video[i].title) 
            //        console.log(responsevideo) 
             videometrics = { 
              id: responsevideo.items[0].id, 
              views: responsevideo.items[0].statistics.viewCount, 
              likes: responsevideo.items[0].statistics.likeCount, 
              dislikes: responsevideo.items[0].statistics.dislikeCount, 
              favorites: responsevideo.items[0].statistics.favoriteCount, 
              comments: responsevideo.items[0].statistics.commentCount 
             }; 
            videodetails.push(videometrics); 
            deferred.resolve(responsevideo); 
            /*detailsOnVideos = $scope.videometrics;*/ 

           }) 
          /* videodetails.push(videometrics);*/ 
         } 
         /*promises.push(videodetails);*/ // PROMISE 

         console.log(videodetails); 
         /* console.log(promises);*/ //PROMISE LOGGER 
/*      console.log(videodetails);*/ 
         console.log($scope.video); 
         console.log("") 
         pagetokenarr = response.nextPageToken; 
         console.log(pagetokenarr) 

        }); 
       return deferred; 
       /*return $q.all(promises);*/ // PROMISE 

當你看到我的第一個http get,是functionel,但下一個不是。我不明白爲什麼。但是,如果我把我的videodetails數組放入promise數組中,它就可以工作。然後再次。我不知道爲什麼。

回答

1

下面是這個plunker

您的代碼工作是相當多的工作的解決方案。問題在於你的console.log()被解僱得太早,因爲它不在你的承諾的.success().then()中。它在調用$http調用之前被解僱。

我重寫了一下你的代碼(特別是這些for循環),使它更具可讀性。

而且你不需要建立自己的諾言,直到$http調用返回的承諾

下面是最終代碼:

$http.get('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=' + playlistId + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA') 
    .success(function (response) { 
     angular.forEach(response.items, function(item){ 
      var video = { 
        id: item.snippet.resourceId.videoId, 
        title: item.snippet.title 
      }; 
      $scope.video.push(video); 
     }) 
     console.log($scope.video); 
     angular.forEach($scope.video, function(video){ 
      httpcalls.push($http.get('https://www.googleapis.com/youtube/v3/videos?part=statistics&id=' + video.id + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA') 
       .success(function (responsevideo) { 
        videometrics = { 
          id: responsevideo.items[0].id, 
          views: responsevideo.items[0].statistics.viewCount, 
          likes: responsevideo.items[0].statistics.likeCount, 
          dislikes: responsevideo.items[0].statistics.dislikeCount, 
          favorites: responsevideo.items[0].statistics.favoriteCount, 
          comments: responsevideo.items[0].statistics.commentCount 
         }; 
        $scope.videodetails.push(videometrics); 
       })); 
     }); 
     pagetokenarr = response.nextPageToken; 
     $q.all(httpcalls).then(function(){ 
      console.log($scope.videodetails); 
     }) 

    }); 

注意,我把所有的$http呼叫到一個集合(httpcalls )並將你的console.log包裝成一個$q.all(httpcalls).then()函數。這將等到所有$http調用進入集合爲止。

希望它有幫助。

+0

非常感謝!我已經嘗試了很多forEach(第一次我嘗試了他們),現在我知道他們是如何工作的。我明白了你對在http調用之前執行的console.log的看法。完善! – SpaceChimps

+0

我的文章解釋了爲什麼它不能正常工作並給出解決方法。但是爲了更清晰地完成$ http調用(服務),請記住@Sphaso的答案 – Okazari

0

你的代碼似乎工作正常。我已經刪除了除了必需品之外的所有東西,添加了我需要的作爲佔位符的變量,因爲我不確定playlistId等。下面是我測試過的代碼。

var app = angular.module('app', []); 
app.controller('ctrl', function ($scope, $http) { 
var videometrics; 
$scope.videodetails = []; 
var playlistId = "PL63F0C78739B09958"; 
$scope.video = []; 
$http.get('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=' + playlistId + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA') 
    .success(function (response) { 
     for (var i = 0; i < response.items.length; i++) { 
      var video = { 
       id: response.items[i].snippet.resourceId.videoId, 
       title: response.items[i].snippet.title 
      }; 
      $scope.video.push(video); 
     } 
     for (i = 0; i < $scope.video.length; i++) { 
      $http.get('https://www.googleapis.com/youtube/v3/videos?part=statistics&id=' + $scope.video[i].id + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA') 
      .success(function (responsevideo) { 
       var videometrics = { 
        id: responsevideo.items[0].id, 
        views: responsevideo.items[0].statistics.viewCount, 
        likes: responsevideo.items[0].statistics.likeCount, 
        dislikes: responsevideo.items[0].statistics.dislikeCount, 
        favorites: responsevideo.items[0].statistics.favoriteCount, 
        comments: responsevideo.items[0].statistics.commentCount 
       }; 
       $scope.videodetails.push(videometrics); 
      }); 
     } 
    }); 
}); 

當它在作用域上可用時,它將在瀏覽器中使用{{videodetails}}顯示。

如果您需要使用數據而不是僅顯示數據,您可能需要使用其他答案所建議的服務。

+0

這裏的問題是,第二個循環,我需要得到具體的指標。當即時將這些數據保存在一個數組中時,該數組似乎是空的。 – SpaceChimps

+0

我上面編輯了我的答案,以便它將顯示所有特定指標。 – craigo

2

你不需要$ q和$ http。基本上有兩種方式(我知道)與$ http一起工作:

1)創建服務,在那裏隔離$ http。返回承諾這樣:

return $http.get({params...}).then(function(data) { 
    return data.result; 
}); 

然後在控制器你必須:

SuperService.get(params...).then(function(data) { $scope.something = data; }); 

2)數據綁定!做一個服務,把$ http放在那裏。但是這次你將結果綁定到服務中的一個對象。在該服務中,您還有一個返回該對象的方法。

$http.get({params...}).then(function(data) { 
    myObject = data.result; 
}); 

然後在控制器:

$scope.spiderman = SuperService.getObj(); 
SuperService.get(params...); 

當你調用獲得()AngularJS做它的魔力和更新$ scope.spiderman(只要你從服務器的響應,當然)。

相關文獻:

+0

這似乎是一個好主意。我會嘗試一下。謝謝。 – SpaceChimps

+0

不客氣! – Sphaso

+0

它實際上並不能解釋爲什麼OP代碼無法正常工作,但這仍然是關於此的最佳實踐。 – Okazari