简体   繁体   English

jQuery中带有循环的setTimeout

[英]setTimeout in jQuery with a loop

I have an array of words and I would like to change a div tag to each word in sequence with a delay. 我有一个单词数组,我想按顺序将div标签更改为每个单词。

<script>
    function printWord(w) {
    setTimeout(function() {
        $("#word").text(w);
        }, 1000);

     }

function readBook() {
    var array = $("#offscreen_text").text().toString().split(/[\s\n]+/);
    for (i =1; i < array.length; i++){
        printWord(array[i]);
    }

}
</script>
<body onload="readBook()">
<div id="word"></div>
<div id="offscreen_text">hi hello bye goodbye this is a test with some random text</div>
</body>

When I run readBook() nothing seems to be happening. 当我运行readBook()似乎什么都没有发生。

You can use setInterval without using a for loop. 您可以使用setInterval而不使用for循环。

function readBook() {
    var array = $("#offscreen_text").text().toString().split(/[\s\n]+/);
    var i=0;
    setInterval(function(){
        $("#word").text(array[i]); i++;    
    },1000);   
}

Demo : http://jsfiddle.net/sywzno5p/ 演示: http : //jsfiddle.net/sywzno5p/

Edit Fiddle with clearInterval() : http://jsfiddle.net/gn6eh7t1/ 使用clearInterval()编辑小提琴: http : //jsfiddle.net/gn6eh7t1/

Array indices are 0-based. 数组索引从0开始。

for (i = 1; i < array.length; i++)

should be 应该

for (i = 0; i < array.length; i++)
//       ^

printWord(w)

doesn't account for a successive delay. 不考虑连续的延迟。 The first time it's called, it'll tell the script to wait 1000ms before continuing, and every successive call (which will happen at approximately 1ms after the previous call) will also wait 1000ms. 第一次调用它时,它将告诉脚本在继续之前等待1000ms,然后每个后续调用(将在上一次调用后大约1ms发生) 将等待1000ms。 What this means is that the script will wait approximately 1 second before showing the last word. 这意味着脚本将在显示最后一个单词之前等待大约1秒钟。

If you're going to keep using setTimeout change the function to something along the lines of: 如果您要继续使用setTimeout请将函数更改为以下内容:

function printWord(w, d) {
    setTimeout(function() {
        $("#word").text(w);
    }, 1000 * d);
}

You're using jQuery as a dependency. 您正在使用jQuery作为依赖项。 Read the API and USE IT , or drop the dependency. 阅读API并使用USE IT或删除依赖项。

.text() always returns a string. .text()始终返回一个字符串。 .toString() is unnecessary. .toString()是不必要的。 Get rid of it. 摆脱它。

$("#offscreen_text").text().toString().split(/[\s\n]+/);
//                         ^^^^^^^^^^^

Also, \\s matches \\n , so [\\s\\n] is redundant. 另外, \\s匹配\\n ,因此[\\s\\n]是多余的。 Simplify to /\\s+/ 简化为/\\s+/

jQuery(function ($) {}) is the aliasing short-hand for document.ready , which is the appropriate way to call readBook : jQuery(function ($) {})document.ready的别名缩写,是调用readBook的适当方法:

function readBook($) {
    ...
}

jQuery(readBook);

setTimeout has no queueing behavior. setTimeout没有排队行为。 Use delay(1000) and queue(fn) : 使用delay(1000)queue(fn)

function printWord(w) {
    $('#word').delay(1000).queue(function (next) {
        $(this).text(w);
    });
}

You made a mistake iterating with a simple for loop. 您在使用简单的for循环进行迭代时犯了一个错误。 jQuery has a utility $.each method which would have prevented such a simple error: jQuery有一个实用程序$.each方法,它可以防止这样一个简单的错误:

$.each(array, function (index, value) {
    ...
});

All together now 现在都在一起了

 jQuery(function ($) { var words; words = $('#offscreen_text').text().split(/\\s+/); $.each(words, function (i, word) { $('#word').delay(1000).queue(function (next) { $(this).text(word); next(); }); }); }); 
 #offscreen_text { display: none; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="word"></div> <div id="offscreen_text">hi hello bye goodbye this is a test with some random text</div> 

See http://jsfiddle.net/ta9q32v7/ 参见http://jsfiddle.net/ta9q32v7/

function readBook() {
    var array = $("#offscreen_text").text().toString().split(/[\s\n]+/);
    var i = 0;
    setInterval(function(){ $("#word").text(array[i % array.length]); i++;}, 1000);
}

readBook();

I have created a jsfiddle with a solution for you. 我创建了一个jsfiddle并为您提供了解决方案。 The readBook() method was not being called. 未调用readBook()方法。 If you did call it with it written the way you have it it would seem as though it only did the last word of the array because the setTimeoutswould all happen at once since they all were called while the loop was being iterated (nearly at the same time)... to fix this i simply added a multiplier to the timeout for how far in the loop you are. 如果您确实用它编写的方式调用它,则好像它只执行了数组的最后一个字,因为setTimeouts会一次发生,因为它们都是在循环循环时被调用的(几乎是同一时间)时间)...以解决此问题,我只是在超时中添加了一个乘数,以了解您在循环中的距离。 This solution is probably not very efficient though since it will set as many timeouts as there are words. 尽管此解决方案可能会设置与单词一样多的超时,但它可能不是很有效。

also, you have i=1 which others have stated will skip the first word of the array. 同样,您有i = 1,其他人已经说过将跳过数组的第一个单词。

http://jsfiddle.net/782pmv64/2/ http://jsfiddle.net/782pmv64/2/

function printWord(w, i) {
  setTimeout(function() {
    $("#word").text(w);
    }, 800 * i);
}

You are calling the printWord function over and over without giving it time to execute the code, so each time it runs, it overwrites the previous run, giving it only chance to print the last word... 您不停地重复调用printWord函数而没有时间来执行代码,因此每次运行时,它都会覆盖前一次运行,从而仅使它有机会打印最后一个单词。

I modified your code to be a single function that only calls itself when it knows that there are more words to be "read". 我将您的代码修改为单个函数,仅在知道有更多单词需要“读取”时才调用自身。

I declared the array in the global scope as well as the iterator for the word count. 我在全局范围内声明了数组以及单词计数的迭代器。 the function readBook will increment the iterator once a word has been 'read'. 一旦单词被“读取”,readBook函数将使迭代器递增。

Please run the code snippet. 请运行代码段。

 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="word"></div> <div id="offscreen_text">hi hello bye goodbye this is a test with some random text</div> <script> var i = 0; var array = $("#offscreen_text").text().toString().split(/[\\s\\n]+/); function readBook() { $("#word").text(array[i]); i++; if (i < array.length) { setTimeout(readBook, 1000); } } readBook(); </script> 

The Problems: 问题:

  1. All the printWord calls are made at the same time, so every setInterval call within the function will fire at roughly the same time. 所有的printWord调用都是在同一时间进行的,因此函数内的每个setInterval调用都将在大致相同的时间触发。
  2. Array indexes start at 0 , so i =1 will skip the first word. 数组索引从0开始,所以i =1将跳过第一个单词。
  3. While not a problem so much as it is unpleasant, you don't need to use onload when using jQuery, you can use jQuery's document.ready . 尽管这不是一个令人不愉快的问题,但使用jQuery时无需使用onload ,而可以使用jQuery的document.ready
  4. Also, there is no need to call .toString() on $("#offscreen_text").text() , since jQuery.text will always return a string, even if no elements are selected. 另外,也不需要在$("#offscreen_text").text() .toString()上调用.toString() ,因为即使未选择任何元素, jQuery.text也会始终返回字符串。

A Solution: 一个解法:

You could use a setTimeout -based loop to iterate over the words. 您可以使用基于setTimeout的循环遍历单词。

 $(function() {//document.ready wrapper (no need for onload). function readBook() { var array = $("#offscreen_text").text().split(/[\\s\\n]+/); var wordIndex = 0;//Keep track of the word to show. var nextWord = function() { if (wordIndex < array.length) {//Check if there are more words to show. $("#word").text(array[wordIndex]);//Set the word. setTimeout(nextWord, 1000);//Set the next word timeout. wordIndex++;//Increment the word counter. } } nextWord();//Start the word loop. } readBook(); }); 
 #offscreen_text { display: none; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div id="word"></div> <div id="offscreen_text">hi hello bye goodbye this is a test with some random text</div> 

Don't like to over complicating things like this, solution could be as easy as 不想过分复杂,这样的解决方案可能很简单

function printWord(word,index,life) {
    setTimeout(function() {
         $("#word").text(word);
    }, index*life);

}

function readBook() {
    var array = $("#offscreen_text").text().split(/[\s\n]+/);

    for (i =0; i < array.length; i++){
        printWord(array[i],i,1000);
    }

}

$(readBook);

Basically you are having the time that the action takes place occur X amount of time after the previous 基本上,您有时间进行操作,发生时间是前一个

also this is something that can be done without using jQuery 这也是无需使用jQuery即可完成的操作

 function printWord(w,i,life) {

    setTimeout(function() {
        document.getElementById("word").innerText = w;
    }, i*life);

 }

function readBook() {
    var array = document.getElementById("offscreen_text").innerText.split(/[\s\n]+/);

    for (i =0; i < array.length; i++){
        printWord(array[i],i,1000);
    }

}

document.addEventListener('DOMContentLoaded', readBook);

Everything is happening at once. 一切都在发生。 I passed in the index value i to multiply by the 1000 ms. 我传入索引值i乘以1000毫秒。

<!DOCTYPE html>
<html>
<head>
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
</head>
<body onload="readBook()">
<div id="word"></div>
<div id="offscreen_text">hi hello bye goodbye this is a test with some random text</div>
<div id="sentence">This is some sentence that has the word is.</div>
<script>
    function printWord(w,i) {
    setTimeout(function() {
        $("#word").text(w);
        }, 1000*i);

     }

function readBook() {
    var array = $("#offscreen_text").text().toString().split(/[\s\n]+/);
    for (i =0; i < array.length; i++){
        printWord(array[i],i);
    }

}
</script>
</body>
</html> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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