如何为我的循环函数进行回调

时间:2014-06-26 15:39:10

标签: javascript json callback jquery-deferred each

我有一个保存网址的JSON文件。我创建了一个$.each()循环来浏览JSON文件,然后在循环的每次迭代中执行一个SoundCloud函数。因此,为了获得相同的循环结果,我必须在每次迭代后为SoundCloud函数进行回调。这是我试过的:

$.getJSON("http://www.json-generator.com/api/json/get/bLjOHIYsAy?indent=2", function(data){ //Link of the playlist

$.each(data.PlayListArray, function(key, val){ //navigate to array called PlayListArray
     var songLink = val.URL; // the value of URL in the array
}, function(){// Callback Function
    SC.get('/resolve', { url: songLink }, function(track) { 
        $("#demo").append("<p id= "+ track.id + ">" + track.title + "</p>");
    });
 });
});

如果这个回调不起作用,并且不显示来自SoundCloud的SC.get()函数的收集数据。 有什么想让它发挥作用吗?或者我如何使用延迟方法来制作一系列函数?

演示:http://jsfiddle.net/Fq2Rw/5/

3 个答案:

答案 0 :(得分:1)

你在这里做的是将第三个参数传递给每个,只有两个参数。除非我遗漏了您确切目标的内容,否则下面的代码应该按预期工作。

SC.initialize({
    client_id: "b8f06bbb8e4e9e201f9e6e46001c3acb",
});

$.getJSON("http://www.json-generator.com/api/json/get/bLjOHIYsAy?indent=2", function(data){ //Link of the playlist
    $.each(data.PlayListArray, function(key, val){ //navigate to array called PlayListArray
        var songLink = val.URL; // the value of URL in the array

        SC.get('/resolve', { url: songLink }, function(track) { 
            $("#demo").append("<p id= "+ track.id + ">" + track.title + "</p>");
        });
    });
});

编辑:我现在明白你想按照data.PlayListArray结果集定义的顺序得到结果。我认为你需要缓冲结果并仅在收到所有答案时处理它们。下面的代码可能不是最佳的,但它可能会给你一些新的想法。

当然,没有办法控制不同的SC.get()&#39;将响应,并因此,您的功能(跟踪)&#39;将调用回调。在进行下一次通话之前等待每个答案 - 就像您的原始帖子所暗示的那样 - 确实是另一种可能性,但它会比并行进行所有呼叫要慢得多(如下面的代码所示)。

SC.initialize({
    client_id: "b8f06bbb8e4e9e201f9e6e46001c3acb",
});

$.getJSON("http://www.json-generator.com/api/json/get/bLjOHIYsAy?indent=2", function(data){ //Link of the playlist
    var answer = {};

    $.each(data.PlayListArray, function(key, val){ //navigate to array called PlayListArray
        var songLink = val.URL; // the value of URL in the array
        SC.get('/resolve', { url: songLink }, function(track) {
            answer[songLink] = track;
            if(Object.keys(answer).length == data.PlayListArray.length) {
                // we've got all results: let's process them by iterating on data.PlayListArray again
                $.each(data.PlayListArray, function(key, val){
                    var track = answer[val.URL];
                    $("#demo").append("<p id= "+ track.id + ">" + track.title + "</p>");
                });
            }
        });
    });
});

答案 1 :(得分:1)

如果你想在循环中进行异步调用,经验法则是使用递归函数而不是for循环。

function loop(i){
    if(i >= data.PlayListArray.length){
        //DONE
    }else{
        SC.get('blabla', function(track){
          //Loop body
          loop(i+1);
        });
     }
}

loop(0);

正如Arnaulid已经指出的那样,这种顺序执行的回调将会导致高延迟,所以首先要确保这是你真正想做的事情。

答案 2 :(得分:1)

正如已经指出的那样,$.getJSON接受参数(url,callback),但是,你也可以链接.then(callback),这是&#34; promisy&#34;这样做的方法。

确保显示的列表与派生它的数组的顺序相同的最简单方法是附加一个空的p元素,然后在数据到达时用数据填充它。您可以依赖$.each函数形成的闭包来保持对附加p的可靠引用。

$.getJSON("http://www.json-generator.com/api/json/get/bLjOHIYsAy?indent=2").then(function(data) { //Link of the playlist
    var $demo = $("#demo");
    $.each(data.PlayListArray, function(i, item) { //traverse the PlayListArray array
        var $p = $("<p/>").appendTo($demo);//appending an empty <p></p> here ensures the observable playList will be in the same order as data.PlayListArray. 
        SC.get('/resolve', { url: item.URL }, function (track) {
            $p.attr('id', track.id).text(track.title);//flesh out the <p></p> appended above. $p remains available due to closure formed by the outer function.
        });
    });
});

另请注意,通过分配$demo ouside循环可避免在每个循环的每次迭代中在DOM中发现$("#demo")的效率低下。

<强> Updated fiddle