javascript - 如何使用多个 api 调用填充数组?

标签 javascript arrays scope spotify

我一直在尝试弄清楚如何通过连续调用 Spotify API 来填充这个“艺术家”数组。我试图用用户保存的库中的每位艺术家填充“艺术家”数组。调用的工作方式是,每次调用都会返回最多 50 位艺术家的数据 block 。然而,当我在这里填充数组,然后尝试将新的 i 值传递给 getUserData 函数时,我认为 i 值没有更新,并且由于某种原因,我的“艺术家”数组仅填充到 226,而“总计” ' 我的测试用例的值为 276。有人可以帮我弄这个吗?我认为这可能是一个范围问题,但我不知道在哪里。预先感谢您!

var i = 0;
function getUserData(accessToken, i) {
    return $.ajax({
        url: 'https://api.spotify.com/v1/me/tracks?limit=50&offset=' + i,
        headers: {
           'Authorization': 'Bearer ' + accessToken
        }
    });
}

 var artists = [];
 loginButton.addEventListener('click', function() {
      login(function(accessToken) {


       getUserData(accessToken, i)
            .then(function(response) {
            var total = response.total;

            while(i < total) {
            i+=50;
             getUserData(accessToken, i)
            .then(function(response) {
                total = response.total;
                alert(total); //testing
                loginButton.style.display = 'none';

for (var j = 0; j < 50 && artists.length < total; j++){                         

    artists.push(response.items[j].track.album.artists[0].name);
}
         alert(artists[7] + artists.length); //testing
         alert(artists[artists.length - 1]); //testing
            });
            }  


            });



        });
});

感谢您的帮助!

最佳答案

while 循环中的第一个 getUserDatai = 50 开始 - 因此前 50 个不会被插入 artists 数组

添加

for (var j = 0; j < 50 && artists.length < total; j++) {
    artists.push(response.items[j].track.album.artists[0].name);
}

在 while 循环之前 - 就像这样

var artists = [];
loginButton.addEventListener('click', function() {
    login(function(accessToken) {
        var i = 0;
        getUserData(accessToken, i)
        .then(function(response) {
            var total = response.total;
            // added code to store the first 50 artists
            for (var j = 0; j < 50 && artists.length < total; j++) {
                artists.push(response.items[j].track.album.artists[0].name);
            }
            // end added code
            while (i < total) {
                i += 50;
                getUserData(accessToken, i)
                .then(function(response) {
                    total = response.total;
                    alert(total); //testing
                    loginButton.style.display = 'none';

                    for (var j = 0; j < 50 && artists.length < total; j++) {
                        artists.push(response.items[j].track.album.artists[0].name);
                    }
                    alert(artists[7] + artists.length); //testing
                    alert(artists[artists.length - 1]); //testing
                });
            }
        });
    });
});

唯一的问题是艺术家的顺序可能是“错误的”,因为其中一个异步 getUserData 可能比下一个异步 getUserData 花费更长的时间(网络问题是不可预测的)

您可以重写代码以使用 Array#mapArray#concat$.when - 并通过以下方式保留数据顺序这样做

I'm assuming response.total is the total number of tracks, regardless of the offset and limit as this is implied by your code

loginButton.addEventListener('click', function() {
    login(function(accessToken) {
        loginButton.style.display = 'none';
        var arr = [getUserData(accessToken, i)];
        arr[0]
        .then(function(response) {
            for (var i = 50; i < response.total; i += 50) {
                arr.push(getUserData(accessToken, i));
            }
            $.when.apply($, arr)
            .then(function() {
                var artists = [].concat.apply([], [].map.call(arguments, function(response) {
                    return response.items.map(function(item) {
                        return item.track.album.artists[0].name;
                    });
                }));
                // artists array is filled, now do what you need
            });
        })
        .catch(function(err) {
            // handle errors here
        });
    });
});

如上所述,但使用 native Promise.all

loginButton.addEventListener('click', function() {
    login(function(accessToken) {
        loginButton.style.display = 'none';
        var arr = [getUserData(accessToken, i)];
        arr[0]
        .then(function(response) {
            for (var i = 50; i < response.total; i += 50) {
                arr.push(getUserData(accessToken, i));
            }
            Promise.all(arr).then(function(chunks) {
                var artists = [].concat.apply([], chunks.map(function(response) {
                    return response.items.map(function(item) {
                        return item.track.album.artists[0].name;
                    });
                }));
                // artists array is filled, now do what you need
            });
        })
        .catch(function(err) {
            // handle errors here
        });
    });
});

关于javascript - 如何使用多个 api 调用填充数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41205833/

相关文章:

swift - 定义一个在 Swift 中调用自定义函数的中缀运算符

facebook - 为什么我请求 oauth 的电子邮件范围,Facebook 也显示我需要访问 friend 列表?

javascript - 如何使用 javascript 获取 itemLabel 表单 JSP 的值

javascript - Facebook 移动版 Safari 无法正常工作

php - 更改 API 数据输出的布局

javascript - 从数组中取出第一个具有唯一 ID 的对象并将它们放入新列表中

javascript - 使整个网页着色

javascript - 如何在 webpack 上获取原始静态 html 文件

javascript - 数组声明和赋值 (JavaScript)

javascript - Node.js 全局评估,抛出 ReferenceError