使用递归的jQuery追加元素不会逐个显示

时间:2017-07-29 21:28:43

标签: javascript jquery ecmascript-6

我试图使用递归函数将段落附加到容器。

代码看起来像这样 -

loadSections (sections, buttons) {
        let sectionLength = sections.length;
        let self = this;
            this.sleep(sections[sectionCounter].DelayInMs);
            let context = {
              message: sections[sectionCounter].Text,
            };
            this.fillSections(context, function () {
                sectionCounter ++;
                if (sectionCounter < sectionLength) {
                    self.loadSections(sections, buttons);
                }
            });
    }

    fillSections (context, callback) {
        let messageList = $(document.createElement('p'));
        messageList.html(context.message);
        $('.chat-flow-container').append(messageList);
        callback();
    }

    sleep (milliSeconds) {
        let start = new Date().getTime();
        let expire = start + milliSeconds;
        while (new Date().getTime() < expire) { }
        return;
    }

代码正常运作。但问题是所有附加 p 元素到 .chat-flow-container 都没有显示我在睡眠方法中提到的延迟,相反它们一起显示在一起递归结束。

1 个答案:

答案 0 :(得分:0)

sleep方法中的繁忙循环阻止浏览器更新屏幕。它会阻止浏览器。所以这不是一个好的方法。

而是使您的代码异步。如果您支持async/await,那么您可以这样做:

async loadSections(sections, buttons) {
    for (let section of sections) {
        await this.sleep(section.DelayInMs);
        let context = {
            message: section.Text,
        };
        this.fillSections(context);
    }
}

fillSections (context) {
    let messageList = $(document.createElement('p'));
    messageList.html(context.message);
    $('.chat-flow-container').append(messageList);
}

sleep (milliSeconds) {
    return new Promise(resolve => setTimeout(resolve, milliSeconds));
}

现在loadSections会立即返回,但当setTimeout到期时,其中的代码仍会继续恢复。

const sections = [
  { DelayInMs:  300, Text: 'A' },
  { DelayInMs: 1000, Text: 'B' },
  { DelayInMs: 1000, Text: 'C' },
];
class X {
    async loadSections(sections, buttons) {
        for (let section of sections) {
            await this.sleep(section.DelayInMs);
            let context = {
                message: section.Text,
            };
            this.fillSections(context);
        }
    }

    fillSections (context) {
        let messageList = $(document.createElement('p'));
        messageList.html(context.message);
        $('.chat-flow-container').append(messageList);
    }

    sleep (milliSeconds) {
        return new Promise(resolve => setTimeout(resolve, milliSeconds));
    }
}

new X().loadSections(sections);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="chat-flow-container"></div>