2015-03-21 3 views
0

У меня есть функция для вывода массива с именем DisplayComments(comments). В рамках этой функции я делаю вызов ajax для извлечения replies, связанного с comments.ajax вызов в каждом цикле функции как не ожидалось

Когда Аякс запускается, чтобы получить replies, после того, как массив возвращается из контроллера Web API, код выпрыгивает из Аякса и просто перейти к последней строке each loop, которая $('#div_ListOfComments').append(replies);. Затем он возвращается к первой строке цикла, которая равна var cid = comment.CommentId;, и продолжит следующий элемент комментария. Затем вызов ajax происходит для второго comment, и он ведет себя одинаково. Он никогда не посещает статус ajax Success, пока each loop не будет заполнен для всех comments. Затем он переходит в раздел Success и запускает код один раз для каждого элемента 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); 
     }); 
    } 

ответ

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

2

Ajax является асинхронным. Вызов $.ajax() инициирует только вызов ajax. Затем строка кода после его выполнения. Обратный вызов success не вызывается до тех пор, пока сервер не вернет ответ на вызов ajax.

Вы также не можете рассчитывать на ответы 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

+0

Мой ответ отвечает на ваш вопрос, почему ваш код не работает, и предлагает два пути, чтобы исправить это. Ответ Леонардо не является третьей альтернативой, а вместо этого является другим способом реализации моего первого предложения. –

Смежные вопросы