使用来自一个API调用的响应来执行另一个API调用

时间:2017-03-29 07:28:04

标签: javascript angularjs asynchronous

我正在使用AngularJS构建一个网站,其中一个功能是为指定日期提供Billboard(它是音乐图表)列表。 我想按顺序呈现歌曲,以及歌曲的图像。

首先我要调用此API:

http://billboard.modulo.site/

我在那里给出一个日期,并获得该日期前10首歌曲的回复以及每首歌曲的数据。

Billboard API的响应还包括 spotify id ,我想使用该ID并调用Spotify Web API来获取该歌曲的图像,以补充我提供的有关每首歌曲的信息歌曲。

这就是我的控制器中的样子:

var spotifyID = [];
$scope.spotifyImg = [];

musicService.getBillboard($scope.date).then(function(data){ //Response is top 10 songs for given date
        $scope.status = "";
        $scope.songlist = data;
        for (var i = 0; i < data.length; i++) {
            spotifyID[i] = data[i].spotify_id; //data[i].spotify_id returns the ID of the track, as given by the billboard API
        }
        $scope.getImages();
    });

$scope.getImages = function() {
    for (var i = 0; i < spotifyID.length; i++) {
        if(spotifyID[i] !== null) {
            musicService.getSpotify(spotifyID[i]).then(function(data){ 
                $scope.spotifyImg[i] = data.album.images[0].url; //returns the appropriate image from the Spotify Web API
        });
    }
    }
    console.log($scope.spotifyImg);
}

在我看来,它看起来像这样:

<div ng-repeat = "song in songlist">
    <div>{{ song.rank }}</div>
    <div>
        <img ng-src=" {{ spotifyImg[$index] }}"/>
    </div>
</div>

然而,它不起作用。

当我在控制台中检查$ scope.spotifyImg数组时,它的长度为11,并且索引10中只有一个元素,这是最后一首歌曲的图像(即第10首歌曲)。

我有点困惑为什么$ scope.spotifyImg数组只包含索引10中的一个元素。另外,为什么当spotifyID的长度为10时,长度为11的数组?

关于如何解决这个问题的任何想法?

4 个答案:

答案 0 :(得分:1)

创建单独的函数并将for循环的内容放在该函数中并在循环中调用该函数

$scope.getImages = function() {
    for (var i = 0; i < spotifyID.length; i++) {
        if (spotifyID[i] !== null) {
            sampleFunc(i);
        }
    }
}

function sampleFunc(i) {
    musicService.getSpotify(spotifyID[i]).then(function(data) {
        $scope.spotifyImg[i] = data.album.images[0].url; //returns the appropriate image from the Spotify Web API
    });
}

我认为你只得到一个数组的最后一个索引的原因是当你在循环中调用promise时,循环不会等到promise返回。它只是继续执行。时间promise返回循环执行它;它获取数组的最后一个索引。这就是为什么你需要分别从for循环中调用promise

答案 1 :(得分:1)

问题是getSpotify是异步运行的,当对这些调用的响应进入时,i可能设置为spotifyID.length - 1,这意味着所有回调函数都设置{{1}元素。

试试这个:

&#13;
&#13;
$scope.spotifyImg[spotifyID.length - 1]
&#13;
&#13;
&#13;

答案 2 :(得分:1)

您可以使用IIFE

(function(i){
        musicService.getSpotify(spotifyID[i]).then(function (data) {

          $scope.spotifyImg[i] = data.album.images[0].url;
        });
 })(i)

因此,您的getImages函数应该是这样的。

$scope.getImages = function () {
for (var i = 0; i < spotifyID.length; i++) {
    if (spotifyID[i] !== null) {
        (function(i){
             musicService.getSpotify(spotifyID[i]).then(function (data) {

                $scope.spotifyImg[i] = data.album.images[0].url;
             });
        })(i)

    }
}

}

答案 3 :(得分:0)

尝试使用此代码

Js代码

  var spotifyID = [];
      $scope.spotifyImg = [];
      musicService.getBillboard($scope.date).then(function(data) { //Response is top 10 songs for given date
        $scope.status = "";
        $scope.songlist = data;
        for (var i = 0; i < data.length; i++) {
          spotifyID[i] = data[i].spotify_id; //data[i].spotify_id returns the ID of the track, as given by the billboard API
        }
        $scope.getImages(0);
      });


      $scope.getImages = function(index) {
        if (index == spotifyID.length) {
          return;
        }

        musicService.getSpotify(spotifyID[index]).then(function(data) {
          $scope.spotifyImg[index] = data.album.images[0].url; //returns the appropriate image from the Spotify Web API

          // call recursive here
          $scope.getImages(index++);

        });
      }
    }

递归调用你的getimages函数,这样就可以在数组中添加你的图像。