Javascript 在继续循环之前,每个函数都在等待函数完成

Javascript 在继续循环之前,每个函数都在等待函数完成,javascript,jquery,Javascript,Jquery,我实际上是在尝试循环遍历一组LI标记,并插入一些文本,以模拟某人编写一个要做的事情列表的样子。它可以工作,但它同时写入每个列表项,而不是等待。有没有一个简单的方法来实现这一点?我这里有一个JS fiddle设置:但是代码看起来像这样。谢谢 function addListItems() { var str = { listitem1:'personal background check', listitem2:'look into my sketchy neighbor',

我实际上是在尝试循环遍历一组LI标记,并插入一些文本,以模拟某人编写一个要做的事情列表的样子。它可以工作,但它同时写入每个列表项,而不是等待。有没有一个简单的方法来实现这一点?我这里有一个JS fiddle设置:但是代码看起来像这样。谢谢

function addListItems() {
var str = {
    listitem1:'personal background check',
    listitem2:'look into my sketchy neighbor',
    listitem3:'look up my driving record',
    listitem4:'pick up milk',
    listitem5:'wash the car'
}

$('.list-container li').each(function(){
    var z = $(this).attr('id');
    var str2 = str[z];
    var delay = 0;
    for (var i = 0; i <= str2.length; i++) {
        (function(str2){
            delay += 100 + Math.floor(Math.random()*11)*6;
            setTimeout(function(){
                appendStr(str2);       
            },delay);
        })(str2[i])
    }
    function appendStr(str2) {
      $('#'+ z).append(str2);
    }
});
}
函数addListItems(){
var str={
清单项目1:“个人背景调查”,
列表项2:“看看我的粗略邻居”,
列表项3:“查看我的驾驶记录”,
列表项4:“拾起牛奶”,
清单项目5:“洗车”
}
$('.list container li')。每个(函数(){
var z=$(this.attr('id');
var str2=str[z];
var延迟=0;

对于(var i=0;i使延迟累积:

var str={
listitem1:'写入第一项',
listitem2:'写入第二项',
listitem3:'编写第三项',
listitem4:'编写第四项',
listitem5:'写第五项'
},累积显示=0;
$('.list container li')。每个(函数(){
var z=$(this.attr('id');
var str2=str[z];
var延迟=累积延迟;

对于(var i=0;i简化如何?使用两个变量在单个循环中迭代稍微修改的数据结构的全部内容。如下所示

var字符串=
[
{“id”:“listitem1”,“text”:“写入第一项”},
{“id”:“listitem2”,“text”:“写入第二项”},
{“id”:“listitem3”,“text”:“写入第三项”},
{“id”:“listitem4”,“text”:“写入第四项”},
{“id”:“listitem5”,“text”:“写入第五项”},
]
var-stringsIndex=0;
var textIndex=0;
AddString();
函数AddString(){
if(stringsIndex=strings[stringsIndex].text.length)
{
stringsIndex++;
if(stringsIndex==strings.length)
{
返回;
}
textIndex=0;
}
$(“#”+字符串[stringsIndex].id).append(字符串[stringsIndex].text[textIndex]);
textIndex++;
var延迟=10+数学下限(数学随机()*11)*6;
setTimeout(AddString,delay);
}
}

我将反转工作方式:

  • 从要编写的字符串开始
  • 对于每个字符串:

  • 查找相应的列表项(按id)
  • 用打字机的方式写出整个字符串
  • 完成后调用下一个迭代

    var strings = [
      'personal background check',
      'look into my sketchy neighbor',
      'look up my driving record',
      'pick up milk',
      'wash the car'
    ];
    
    function iterate(strings, idx)
    {
      if (idx >= strings.length) { return; }
    
      var id = 'listitem' + (idx + 1),
      el = document.getElementById(id);
    
      typewriter(el, strings[idx], 0, function() {
        iterate(strings, idx + 1);
      });
    }
    
    function typewriter(el, str, idx, cb)
    {
      if (idx >= str.length) {
        return cb();
      }
    
      setTimeout(function() {
        el.innerText = str.substr(0, idx + 1);
        typewriter(el, str, idx + 1, cb);
      }, 100 + Math.floor(Math.random() * 11) * 6);
    }
    

  • +1,这是一个写得很好的问题和JSFIDLE示例。我不确定这个问题的解决方案是什么,但我非常确定问题不是
    。each()
    ,而是您使用的
    setTimeout()
    setTimeout()
    是异步执行的,这意味着整个循环以迭代方式完成(并非同时),但完成得非常快,然后
    setTimeout
    函数处理程序在循环完成后开始工作。我想了解一些关于如何使用
    deferred
    链接这些函数的想法。我同意Snixtor的解释,并补充说,您可能应该根据您选择的列表项乘以延迟值重新启用(您可以使用
    each(函数(索引){…
    获取索引)。第一项不需要额外延迟,但您可以将第二项延迟1秒,第三项延迟2秒,以此类推,这将产生每秒添加一个列表项的效果。按照审美学家的建议使用
    deferred
    可能是一个更干净的解决方案。如果您想使用deferred,您还需要在键入时添加一个触发器ng已经完成了。这很容易做到,但最终你可能会有不太容易理解的代码。我建议你还是将其包装成插件式的模式。不需要额外的变量。只需将行
    var delay=0;
    移到
    每个
    之外即可获得相同的结果。谢谢Floyd.I我选择了Snixtor的解决方案,因为我比我原来的解决方案更喜欢它,但我对使用我现有的代码找到解决方案表示赞赏。感谢Snixtor。我最终选择了这个解决方案,因为它对我来说是最容易理解的,因为我必须在整个过程完成后添加回调,并在每次迭代后添加一些附加功能谢谢你,杰克。我最终选择了斯奈克斯特的解决方案,但你对它的理解也很好。
    var strings = 
    [
        { "id":"listitem1", "text": "write the first item" },
        { "id":"listitem2", "text": "write the second item" },
        { "id":"listitem3", "text": "write the third item" },
        { "id":"listitem4", "text": "write the fourth item" },
        { "id":"listitem5", "text": "write the fifth item" },
     ]
    
    var stringsIndex = 0;
    var textIndex = 0;
    
    AddString();
    
    function AddString(){
        if (stringsIndex < strings.length){
            if (textIndex >= strings[stringsIndex].text.length)
            {
                stringsIndex++;
                if (stringsIndex == strings.length)
                {
                    return;
                }
                textIndex = 0;
            }
    
            $("#" + strings[stringsIndex].id).append(strings[stringsIndex].text[textIndex]);
            textIndex++;
    
            var delay = 10 + Math.floor(Math.random()*11)*6;
            setTimeout(AddString, delay);
        }
    }
    
    var strings = [
      'personal background check',
      'look into my sketchy neighbor',
      'look up my driving record',
      'pick up milk',
      'wash the car'
    ];
    
    function iterate(strings, idx)
    {
      if (idx >= strings.length) { return; }
    
      var id = 'listitem' + (idx + 1),
      el = document.getElementById(id);
    
      typewriter(el, strings[idx], 0, function() {
        iterate(strings, idx + 1);
      });
    }
    
    function typewriter(el, str, idx, cb)
    {
      if (idx >= str.length) {
        return cb();
      }
    
      setTimeout(function() {
        el.innerText = str.substr(0, idx + 1);
        typewriter(el, str, idx + 1, cb);
      }, 100 + Math.floor(Math.random() * 11) * 6);
    }