for(var P in ReturnData.Playlist){
var IsLoaded = false;
if(PlayerName == "A"){
LoadNavA(false,false,false, ReturnData.Playlist[P], function(){
IsLoaded = true;
alert();
});
}else{
LoadNavB(false,false,false, ReturnData.Playlist[P],function(){
IsLoaded = true;
});
}
if(IsLoaded == true) continue;
}
这是一个音乐播放系统。LoadNavA
和LoadNavB
函数将曲目异步加载到播放列表中。这些元素必须按正确的顺序排列。当轨道3比轨道2更早加载时,它首先放置轨道3,然后放置轨道2,但是当轨道1和2已经加载时,它应该开始加载轨道3。
当LoadNavA
或LoadNavB
中的回调被调用时,循环应该继续。如何?
您面临的问题是LoadNavA
和LoadNavB
调用异步操作,这些操作可以以任何顺序返回,但是您试图强制执行一些排序。这是一个问题,因为在回调函数实际执行时,循环已经完成,因此您试图阻止处理的尝试是错误的。
// receives a callback and the elements to iterate
function loop(list, fn) {
if (!list || list.length <= 0)
return;
(function chain(i) {
if (i >= list.length)
return;
fn(list[i], function() {
chain(i + 1);
});
})(0);
}
这个函数假设你给了它一个回调函数,这个回调函数将执行一些操作,并且这个操作一旦完成就会启动链中的下一步。为了使这一点具体化,下面是基于您的代码的一个示例。
首先,做一些设置,以便我们可以使用您的示例:
var PlayerName = "B";
var ReturnData = {};
ReturnData.Playlist = ["song1", "song2", "song3"];
function LoadNavA(b1, b2, b3, el, fn) {
// this could be any asynchronous call (e.g. Ajax)
// using setTimeout here for illustration
window.setTimeout(fn, 2000);
}
var LoadNavB = LoadNavA; // for brevity
现在,loop
:
的实际用法loop(ReturnData.Playlist, function(song, next) {
if (PlayerName == "A") {
LoadNavA(false, false, false, song, function() {
alert("LoadNavA: " + song);
next();
});
} else {
LoadNavB(false, false, false, song, function() {
alert("LoadNavB: " + song);
next();
});
}
});
作为loop
的第二个参数的回调函数将对列表中的每个元素执行一次。它接收播放列表中的一个元素和一个称为next
的函数作为参数。这个回调可以自由地执行任何异步操作,只要这些操作在完成后调用next
函数。这是我们前进到播放列表中的下一个元素的机制,这样每个元素都可以重复这个过程。