每个循环中的ajax调用函数都不是预期的

时间:2015-03-21 01:08:33

标签: jquery ajax asp.net-web-api

我有一个输出名为DisplayComments(comments)的数组的函数。在此函数中,我进行了ajax调用以检索与replies关联的comments

运行ajax以检索replies时,从web api控制器返回数组后,代码跳出ajax并转到each loop的最后一行,这是$('#div_ListOfComments').append(replies);。然后它返回到循环的第一行,即var cid = comment.CommentId;并继续下一个注释项。然后,ajax调用发生在第二个comment,它的行为方式相同。在Success完成所有each loop之前,它永远不会访问ajax调用的comments状态。然后,它将移至“成功”部分,并为每个reply项运行一次代码,以在表单上显示它们。

但是,我需要在每条评论下方添加replies,换句话说,我需要在追加replies之后将$('#div_ListOfComments')附加到comment。但是,下面说明的代码不能以预期的方式运行。它附加所有评论。然后它附加回复。任何人都可以看到下面的代码有什么问题吗?

    function LoadCommentsForPost(postid) {
        jQuery.support.cors = true;
        $.ajax({
            url: '/api/Comment/GetCommentsByPost?pid=' + postid,
            type: 'GET',
            contentType: "application/json; charset=utf-8;",
            dataType: 'json',
            success: function (response) {                 

            },
            error: function (x, y, z) {
                alert(x + '\n' + y + '\n' + z);
            },
            complete: function (jqXHR, textStatus) {
                var comments = JSON.parse(jqXHR.responseText);
                comments = comments["$values"];
                DisplayComments(comments);
            }
        });
    }

    function DisplayComments(comments) {

        $('#div_ListOfComments').html('');
        $.each(comments, function (index, comment) {
            //the current comment is appended to $('#div_ListOfComments')

            var cid = comment.CommentId;
            var replies;
            $.ajax({
                url: '/api/Reply/GetRepliesByComment?cid=' + cid,
                type: 'GET',
                contentType: "application/json; charset=utf-8;",
                dataType: 'json',
                success: function (response) {
                    //VS break-point works just before here
                    //and I see a valid return value from VS
                    //the program continue to work outside of the ajax
                    //with this line below: $('#div_ListOfComments').append.....
                },
                error: function (x, y, z) {
                    alert(x + '\n' + y + '\n' + z);
                }
            });

            $('#div_ListOfComments').append(replies);
        });
    }

2 个答案:

答案 0 :(得分:2)

Ajax是异步的。对$.ajax()的调用只是启动ajax调用。然后执行它之后的代码行。在服务器返回对ajax调用的响应之后才会调用success回调。

您也不能指望以您提出请求的相同顺序返回的ajax响应。

你可以这样做:

function DisplayComments(comments) {
    $('#div_ListOfComments').html('');
    $.each(comments, function (index, comment) {
        var cid = comment.CommentId;

        // Append the comment to $('#div_ListOfComments').
        // Append an empty div to $('#div_ListOfComments') that will hold the replies,
        // giving it an id based on cid.

        $.ajax({
            url: '/api/Reply/GetRepliesByComment?cid=' + cid,
            type: 'GET',
            contentType: "application/json; charset=utf-8;",
            dataType: 'json',
            success: function (response) {
                // Put the replies in the div with the id based on cid.
                // cid will have the correct value because this is a closure.
            }
        });
    });
}

另一种方法是在数据中保留注释和回复,直到最后一次ajax调用返回,然后将它们全部添加到页面中。

function DisplayComments(comments) {
    var replies = {};
    var deferreds = $.map(comments, function(comment) {
        var cid = comment.CommentId;
        return $.ajax({
            url: '/api/Reply/GetRepliesByComment?cid=' + cid,
            type: 'GET',
            contentType: "application/json; charset=utf-8;",
            dataType: 'json',
            success: function(reply) {
                replies[cid] = reply;
            }
        });
    });

    // This executes the function when all the ajax calls have returned.
    $.when.apply($, deferreds).then(function() {
        $('#div_ListOfComments').html('');
        $.each(comments, function(i, comment) {
            var reply = replies[comment.id];
            $('#div_ListOfComments').append(comment.text).append(reply);
        });
    });
}

jsfiddle

答案 1 :(得分:1)

John is right。 另外,我建议您更改级联ajax调用的使用。您可以使用延迟/承诺方法。

您的代码将如下所示



function LoadCommentsForPost(){
    jQuery.support.cors = true;
    return $.ajax({
        url: '/api/Comment/GetCommentsByPost?pid=' + postid,
        type: 'GET',
        contentType: "application/json; charset=utf-8;",
        dataType: 'json'
    });
}
function LoadCommentsForPostError(x, y, z) {
    alert(x + '\n' + y + '\n' + z);
}
function RetrievedComments(jqXHR, textStatus)
{
    var comments = JSON.parse(jqXHR.responseText);
    comments = comments["$values"];
    DisplayComments(comments);
}
function DisplayComments(comments) {
    $('#div_ListOfComments').html('');
    $.each(comments, function (index, comment) {
        var cid = comment.CommentId;

        // Append the comment to $('#div_ListOfComments').
        // Append an empty div to $('#div_ListOfComments') that will hold the replies,
        // giving it an id based on cid.

        $.ajax({
            url: '/api/Reply/GetRepliesByComment?cid=' + cid,
            type: 'GET',
            contentType: "application/json; charset=utf-8;",
            dataType: 'json',
            success: function (response) {
            // Put the replies in the div with the id based on cid.
            // cid will have the correct value because this is a closure.
            }
        });
    });
}

$.when(LoadCommentsForPost()).then(RetrievedComments, LoadCommentsForPostError);




更多$.when documentation