简体   繁体   English

等待函数完成,然后再继续执行$ .each函数中的下一个循环

[英]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: 我正在尝试为执行如下操作的聊天应用编写代码:

  • Get conversation list from an AJAX call 从AJAX通话中获取对话列表
  • Populate the left pane of the web page with the conversations returned by the API 用API返回的对话填充网页的左窗格
  • Bind the chat list items to the right side of the pane after the left pane is populated with all the conversations. 在左侧窗格中填充所有对话后,将聊天列表项绑定到该窗格的右侧。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM