javascript - 如何让 .each() 等待每次迭代完成

标签 javascript jquery asynchronous callback promise

我正在使用 this answer on SO 中的打字机效果目的是先输入第一个 div,然后输入第二个 div(当第一个 div 完成输入时)。

<div class="text">
 Lorem ipsum dolor sit amet...
</div>
<div class="text">
 Cras eros augue, tempor...
</div>

JS:

// Create typewrite function as jQuery plugin:
// (From https://stackoverflow.com/a/22266737/3217306)
$.fn.typeText = function() {
    var keystrokeDelay = 10,

        self = this,
        str = self.html(),
        i = 0,
        isTag,
        text;

    self.html("");

    (function type() {
        text = str.slice(0, ++i);
        if (text == str) {
            console.log("completed typing");
            return;
        }
        self.html(text);

        var char = text.slice(-1);
        if (char == "<") {
            isTag = true;
        }
        if (char == ">") {
            isTag = false;
        }

        if (isTag) {
            return type();
        }
        setTimeout(type, keystrokeDelay);
    } ());
};

var textElements = $(".text");

// For each div.text, type them out
textElements.each(function() {
    $(this).typeText();
});

问题是,两者同时输入。我已经尝试了很多不同的事情,涉及 promise 、回调等,但我无法让它们适用于这种情况。

JSFiddle

最佳答案

有很多方法可以做到这一点,我将展示的方法只是其中一种选择:

... 
self.html("");

$.fn.typeText.queue = $.fn.typeText.queue || [] // make a shared variable between the elements that call this function. This will call them in the order that were added

$.fn.typeText.queue.push(function type() {
    text = str.slice(0, ++i);
    if (text == str) {
        console.log("completed typing");
        $.fn.typeText.queue.shift(); // remove first element which just ended
        if ($.fn.typeText.queue.length > 0) { // if there are more
            $.fn.typeText.queue[0]() // start next
        }
        return;
    }
    ...
   setTimeout(type, keystrokeDelay);
});

if ($.fn.typeText.queue.length == 1) { // if its the first element added or no elements are in queue, call it
    $.fn.typeText.queue[0]();
}

};

这适用于任意数量的元素,并按顺序调用它们。如果您希望所有组同时运行,但在每个组内它们按顺序运行,则可以轻松更改函数来实现此目的。一种方法是将数组传递给该方法并使用它而不是 $.fn.typeText.queue

完整代码:

$.fn.typeText = function() {
    var keystrokeDelay = 10,
    
    		self = this,
        str = self.html(),
        i = 0,
        isTag,
        text;

    self.html("");

    $.fn.typeText.queue = $.fn.typeText.queue || []

$.fn.typeText.queue.push(function type() {
        text = str.slice(0, ++i);
        if (text == str) {
            console.log("completed typing");
						$.fn.typeText.queue.shift(); // remove first element which just ended
          if ($.fn.typeText.queue.length > 0) { // if there are more
              $.fn.typeText.queue[0]() // start next
          }
          return;
        }
        self.html(text);

        var char = text.slice(-1);
        if (char == "<") {
            isTag = true;
        }
        if (char == ">") {
            isTag = false;
        }

        if (isTag) {
            return type();
        }
        setTimeout(type, keystrokeDelay);
    })

  if ($.fn.typeText.queue.length == 1) { // if its the first element added or no elements are in queue, call it
      $.fn.typeText.queue[0]();
  }
    
};

var textElements = $(".text");

textElements.each(function() {
    $(this).typeText();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="text">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse condimentum erat non velit euismod, ac tristique orci hendrerit. Nullam varius in sem sed tempor. Maecenas tincidunt, nisi a accumsan maximus, lectus sem congue ligula, eget tempus neque lacus quis arcu. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Quisque at purus eleifend, euismod nibh ut, auctor nulla. Phasellus convallis nulla urna, porta egestas justo sollicitudin sit amet.
</div>
<div class="text">
  Cras eros augue, tempor ut velit ornare, dignissim sollicitudin mi. Duis accumsan diam sed nulla sodales mattis. Pellentesque nec efficitur nunc, vitae rutrum massa. Pellentesque metus metus, consequat in auctor non, lobortis eget ligula. Sed volutpat, dui vulputate congue iaculis, justo massa consequat turpis, id facilisis ex sapien eget ligula. Praesent eu erat lorem. Mauris id dui orci. Mauris vitae urna tortor. Proin luctus id purus non maximus.
</div>

关于javascript - 如何让 .each() 等待每次迭代完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40392475/

相关文章:

javascript - 在 JavaScript 函数中使用 C# for 循环中的迭代变量

javascript - 在 mysql 数组上使用 php 或 javascript 进行演绎过滤搜索

javascript - 如何禁用 "laxcomma"检查?

jquery - 在特定宽度的滚动上显示/隐藏元素,为其他宽度切换

python - 生成器函数和异步生成器函数的用途有什么区别

javascript - Mongoose 的 findOneAndUpdate 和 upsert 中的重复键错误

javascript - 来自 JS 事件的 AngularDart CustomEvent 监听器

php - CodeIgniter flashdata 重定向后不工作

javascript - 如何在php中的datagrid中显示单个数据

java - 如何从java异步发送soap消息