[英]wait for the function to finish before continuing to the next loop in a $.each function
I'm not an expert in JS or jQuery by any means. 无论如何,我都不是JS或jQuery的专家。 I'm trying to write code for a chat app that does something like this:
我正在尝试为执行如下操作的聊天应用编写代码:
Now the issue I'm having is this. 现在我遇到的问题是这个。 After getting the conversation list from the API call, I iterate over the list and bind each item to the pane.
从API调用获取对话列表后,我遍历该列表并将每个项目绑定到窗格。 .each function goes to the next iteration before the bind function is done executing it's code block.
.each函数在绑定函数执行完代码块之前转到下一个迭代。 When the function that has the $.each iterator is done executing, I use ".done()' to populate the chat history of the first conversation item. But since the loop is finished before all conversations are binded properly, the chat list is populated and appears before I can see any conversations. Because of this, I can't bind any events to the conversation.
当具有$ .each迭代器的函数执行完后,我使用“ .done()”填充第一个对话项的聊天记录。但是由于循环在所有对话都未正确绑定之前完成,因此聊天列表是因此,我无法看到任何对话,因此无法填充任何事件。
What I'm trying to achieve is to wait for the bind conversation to finish executing and then continue with the iteration. 我要达到的目的是等待绑定对话完成执行,然后继续进行迭代。
My code is as below: 我的代码如下:
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();
});
Here's my bindConversationItem function 这是我的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);
}
I tried wrapping the code inside a function and using a callback function but I can't seem to get it to work. 我尝试将代码包装在一个函数中并使用一个回调函数,但似乎无法正常工作。 Any solution here is appreciated.
这里的任何解决方案表示赞赏。
Edit 编辑
I have the function "getUser' that is async in the for each loop. Here's what it looks like: 对于每个循环,我都有一个异步的函数“ getUser”。它看起来像这样:
function getUser(userid, callback) {
$.ajax({
url: 'http://localhost:1995//api/member/' + userid
}).done(callback)
}
The best solution of course is to use promises , but as you have reported you do not know very well about the language, this solution does not impact much your original code: 最好的解决方案当然是使用promises ,但是正如您所报告的那样,您对这种语言不是很了解,这种解决方案对您的原始代码影响不大:
Instead $.each loop, execute every iteration at a time, then call the next when the callback fires. 而是$ .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);
}
You can use .queue()
, $.map()
, .promise()
to return results from asynchronous calls in sequential order, perform tasks when all functions in queueName
have completed 您可以使用
.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, eg, `$.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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.