我决不是JS或jQuery的专家。我正在尝试为聊天应用编写代码来执行类似的操作:
现在我遇到的问题是这个。从API调用中获取对话列表后,我遍历列表并将每个项目绑定到窗格。 .each函数在bind函数执行它的代码块之前进入下一次迭代。当具有$ .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);
}
我尝试将代码包装在函数内并使用回调函数,但我似乎无法使其工作。这里的任何解决方案都表示赞赏。
修改
我有功能&#34; getUser&#39;在每个循环中都是异步的。这是它的样子:
function getUser(userid, callback) {
$.ajax({
url: 'http://localhost:1995//api/member/' + userid
}).done(callback)
}
答案 0 :(得分:1)
当然,最佳解决方案是使用promises,但正如您所报告的那样,您对该语言的了解并不多,此解决方案不会影响原始代码:
而是$ .each循环,一次执行每次迭代,然后在回调触发时调用下一个迭代。
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);
}
答案 1 :(得分: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>