2016-09-17 51 views
1

我不是JS或jQuery的專家。我試着寫代碼的聊天應用程序,並像這樣:

  • 獲取會話列表從一個AJAX調用
  • 填充由API返回的談話網頁的左側窗格中
  • 在左窗格填充所有對話後,將聊天列表項綁定到窗格的右側。

現在我遇到的問題是這個。從API調用獲取對話列表後,我遍歷列表並將每個項目綁定到窗格。 。每個函數在綁定函數執行完代碼塊之前進入下一次迭代。當具有$ .each迭代器的函數完成執行時,我使用「.done()」來填充第一個對話項目的聊天記錄,但由於循環在所有對話被正確綁定之前完成,所以聊天列表是在我看到任何對話之前就會出現,因此,我無法將任何事件綁定到對話中。

我試圖實現的是等待綁定對話完成執行,然後繼續迭代

我的代碼如下:

function (data) { 
        $.each(data, function (index, value) { 

         if (value.toUser == loggeduser) { 
          var isMe = false; 
          getUser(value.fromUserID, function (user) { 
           if (user.picturename == 'none') { 
            bindConversationItem(value.chatMessages[0].message, user.username, 'nopic.png', value.conversationID); 
           } 
           else { 
            bindConversationItem(value.chatMessages[0].message, user.username, user.picturename, value.conversationID); 
           } 
          }); 
         } 
         else { 
          getUser(value.toUserID, function (user) { 
           var isMe = true; 
           if (user.picturename == 'none') { 
            bindConversationItem(value.chatMessages[0].message, user.username, 'nopic.png', value.conversationID); 
           } 
           else { 
            bindConversationItem(value.chatMessages[0].message, user.username, user.picturename, value.conversationID); 
           } 

          }); 
         } 
        }); 
       }).done(function (data) { 
        populateFirstConversation(data); 
        bindEvents(); 

       }); 

這是我的bindConversationItem功能

function bindConversationItem(message, username, userimage, index) { 
      var conv_item = '<li> <a href="#" conversation-index = '+index+' class="clearfix">' 
          + '<img src="http://localhost:1995/contents/member/' + userimage + '" alt="" class="img-circle">' 
          + '<div class="friend-name">' 
           + '<strong>' + username + '</strong>' 
          + '</div>' 
          + '<div class="last-message text-muted">' + message + '</div>' 
          + '<small class="time text-muted">Just now</small>' 
          + '<small class="chat-alert label label-danger">1</small>' 
         + '</a>' 
        + '</li>' 


      $("ul.friend-list").append(conv_item); 
     } 

我試過包裝在函數內部的代碼,並使用一個回調函數,但我似乎無法得到它的工作。任何解決方案在這裏表示讚賞

編輯

我有功能「的getUser」這是異步的每個循環這裏是什麼樣子:

  function getUser(userid, callback) { 
      $.ajax({ 
       url: 'http://localhost:1995//api/member/' + userid 
      }).done(callback) 
     } 
+0

什麼功能是異步在你的$ .each,getUser()? –

+0

@AhmedMujtaba getUser調用不返回任何值。 – guest271314

+0

@ guest271314它應該返回什麼?回調函數從Ajax響應中返回數據。 –

回答

1

您可以使用.queue()$.map().promise()回到依順序從異步調用的結果,執行任務時queueName所有功能已經完成

function processQueue (data) { 
 
    return $({}).queue("ajax", $.map(data, function(id) { 
 
    return function(next) { 
 
     return getUser(id, function(val) { 
 
     // do stuff when asynchronous function returns a value 
 
     return $("<div>", {html:"id:" + id + ", value:" + val * Math.PI}) 
 
     .appendTo("body").after("<br>"); 
 
     }, next) // pass `next` function 
 
    } 
 
    })).dequeue("ajax").promise("ajax") 
 
} 
 

 
function getUser(value, callback, next) { 
 
    // do asynchronous stuff, e.g., `$.ajax()` 
 
    return new $.Deferred(function(dfd) { 
 
    setTimeout(function() { 
 
     dfd.resolve(value * 10) 
 
    }, Math.floor(Math.random() * 1500)) 
 
    }) 
 
    // chain `.then()` which calls `callback`, and `.then()` 
 
    // which call next function in `"ajax"` queue 
 
    .then(callback).then(next) 
 
} 
 

 
var arr = [1, 2, 3, 4, 5]; 
 

 
var queue = processQueue(arr); 
 

 
// do stuff when queue completes 
 
queue.then(function(data) { 
 
    console.log("complete") 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"> 
 
</script>

+0

完美的解決方案。花了一些時間瞭解它,但它爲我工作。我只是想知道,如果我想從getUser函數返回值到隊列對象,我該怎麼做?就像我如何讓承諾返回這個值? –

+0

@AhmedMujtaba _「如果我想將getUser函數的值返回給隊列對象,該怎麼辦」_你可以在'jQuery()'包裝的原始對象上創建一個數組,使用'function(next){} this'是原始的jQuery對象,將值推送到對象中的數組,最後在'.then()'檢查'this [0]'處的值。 https://jsfiddle.net/fqxuwsp7/ – guest271314

1

當然最好的解決方案是使用promises,但正如您所報告的,您對語言不太瞭解,此解決方案不會影響您的原始代碼:

改爲$ .each循環,每次執行一次迭代,然後c所有下一個回調火災時。

function (data) { 
    function done() { 
     populateFirstConversation(data); 
     bindEvents(); 
    } 

    function getNextConversation(index) { 
     if (index == data.length) 
      return done(); 

     var value = data[index]; 

     if (value.toUser == ...) { 
      getUser(..., function() { 
       ... 

       getNextConversation(index + 1); 
      }); 
     } else { 
      getUser(..., function() { 
       ... 

       getNextConversation(index + 1); 
      }); 
     } 
    } 

    getNextConversation(0); 
} 
+0

我做了類似於您提供的解決方案的東西,但沒有像預期的那樣工作。我會再試一次。它不應該是getNextConversation而不是getNextUser?也很難使用承諾?我需要改變什麼? –

+0

是的,名稱應該是getNextConversation。發生了什麼錯誤? –

+0

我使用了一個函數回調函數,它傳入了bindConversationItem方法,並增加了索引並調用了回調函數。它沒有改變我的代碼以前的工作方式,但我沒有嘗試查看究竟是什麼錯誤。也許我沒有做對。我會給你的解決方案嘗試 –

相關問題