问题描述
我正在尝试使用回调函数来摆脱代码中的同步ajax调用,但是我不知道该怎么做。 我正在使用Spotify API将所有演出者都放在播放列表中,然后根据该信息执行任务。 该代码的基本逻辑是:
- 获取用户的播放列表选择
- 在这些播放列表中使用艺术家ID填充数组
- 根据数组进行更多的ajax调用。
- 使用第3步中的阵列来执行其他任务。
问题是,如果我不将步骤2和3设置为同步,则步骤4将在步骤2和3之前。 但是我不能只在步骤2的末尾调用步骤3,而在步骤3的末尾调用步骤4,因为它们都发生在while循环中。 无法解决此问题。
调用功能
这个while循环遍历一个多选框中的所有用户选择,并调用ajax函数附加数据。
artistArray = [];
while (artistUrls[i] != null) {
getArtists(artistArray, artistUrls[i]);
i++;
}
doSomethingWithArtistArray(artistArray);
doAnotherThingWithArray(artistsArray);
Ajax功能
使用ajax调用获取艺术家信息并将其附加到数组中
getArtists(artistArray, url) {
(if (url == null) {
return;
}
$.ajax({
async: false,
url: url,
headers: {
'Authorization': 'Bearer ' + access_token
},
error: function() {
console.log("Something went wrong with " + url);
return;
},
success: function(tracks) {
getArtists_Append(artists, frequencyArray, tracks); //Uses a while loop to append all the artist information to artistArray
},
});
//My idea was to call doSomethingWithArtistArray here but that's not working because there might be more calls to make.
console.log("finished getting artists");
return;
}
}
获得艺术家=
getArtists_Append {
while loop that populates the array
}
1楼
问题在于,当您将Ajax请求视为异步时,它们就好像是同步的一样(并且应该那样做以防止阻塞浏览器)。
最好的方法是:
在从Spotify获取多位艺术家的特定情况下,请使用端点来 。 这将减少您需要向Spotify的Web API发出的请求数量。
如果使用回调函数,则将发出Ajax请求。 然后,在其回调中,您将检查是否需要使用下一个块再次发出Ajax请求。 如果您因为完成而无需发出任何其他请求,请调用下一个函数,在本例中为
doSomethingWithArtistArray
。如果您正在使用Promises,则使用
Promise.all()
传递一个Promise.all()
数组,其中每个Promise.all()
都会包装一个Ajax请求。 当您已经知道需要发出什么请求并且不需要来自请求的响应来确定下一个要发出的请求时,此功能很有用。
请查看Spotify开发人员网站上的“ ,以查看使用Web API的一些开源网站。
例如,当时,您可以看到如何在“ 应用第二种选择。 如果有更多的轨道要提取,该函数将向下一个块发出请求,否则不会。
对于第三种选择,由于使用的是jQuery,因此可以使用$.when
来使用promises。
看看 。
如果您喜欢promise的想法并计划对Web API提出其他请求,我建议您使用诸如 (无耻的自我推广)之类的包装器。
这样,您可以简单地执行以下操作:
var api = new SpotifyWebApi();
var promises = [];
promises.add(api.getArtists(['id1', 'id2', 'id3', 'id4', 'id5']));
promises.add(api.getArtists(['id10', 'id11', 'id12', 'id13', 'id14']));
Promise.all(promises).then(function(data) {
// data contains the result of the promises (ajax requests)
// do something with it
});