我有一个输出名为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);
});
}
答案 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);
});
});
}
答案 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);