Javascript: loop through array with delay

I am trying to loop through an array, but I want to output every value of the array with a delay. This is what my real understanding is how it should work:

EDIT

Requested JS script: http://jsfiddle.net/d3whkjww/

loopThroughSplittedText: function(splittedText) { for (var i = 0; i < splittedText.length; i++) { // for each iteration console.log a word // and make a pause after it setTimeout( console.log(splittedText[i]), 1000 ); }; }, 

However, this does not work, and I believe that this is possible because the arguments in the "for" loop must be inside the setTimeout function. But I do not know how to make it work.

All I get is each value of the array at once, but I want them to display with a delay. How to do it?

+6
source share
12 answers

In my example, it will show you how to quote an array massively until you stop. This is just to give you an idea of ​​how you can make a delay. It also shows you when the value is actually displayed.

I would say that you can really create a nice utility from this timer and use it for several purposes and with the help of a utility that will not allow you to repeat large pieces of code.

JavaScript loop example:

 var body = document.body; var splittedText = ["Hello", "World", "How", "Are", "You", "Today"]; loopThroughArray(splittedText, function (arrayElement, loopTime) { body.innerHTML += arrayElement+ ": " + loopTime+ "<br/>"; }, 1000); function loopThroughArray(array, callback, interval) { var newLoopTimer = new LoopTimer(function (time) { var element = array.shift(); callback(element, time - start); array.push(element); }, interval); var start = newLoopTimer.start(); }; // Timer function LoopTimer(render, interval) { var timeout; var lastTime; this.start = startLoop; this.stop = stopLoop; // Start Loop function startLoop() { timeout = setTimeout(createLoop, 0); lastTime = Date.now(); return lastTime; } // Stop Loop function stopLoop() { clearTimeout(timeout); return lastTime; } // The actual loop function createLoop() { var thisTime = Date.now(); var loopTime = thisTime - lastTime; var delay = Math.max(interval - loopTime, 0); timeout = setTimeout(createLoop, delay); lastTime = thisTime + delay; render(thisTime); } } 
+1
source

I tried to match your code as close as possible.

Use it

 var splittedText = ["Hello", "World", "How", "Are", "You", "Today"]; function loopThroughSplittedText(splittedText) { for (var i = 0; i < splittedText.length; i++) { // for each iteration console.log a word // and make a pause after it (function (i) { setTimeout(function () { document.getElementById('text').innerHTML += splittedText[i]; console.log(splittedText[i]); }, 1000 * i); })(i); }; } loopThroughSplittedText(splittedText); 

Demo Screenshot

+6
source

One problem with your code is that i is common to all callbacks. Thus, the first callback said “write the record to index i ”, however, by the time it finishes execution, the first loop has completed, so i now at the end of the text.


One way to achieve what you are looking for is not to use a for loop, but to have a function that (1) prints a character, (2) updates the counter / position and (3) schedules the next character, if necessary:

 loopThroughSplitText: function (text) { var i = 0; function printEntry() { console.log(text[i]); i++; // Increment the position if (i < text.length) { // If there are more chars, schedule another setTimeout(printEntry, 1000); } } printEntry(); // Print the first entry/char } 
+2
source

Well, since this is not an exact duplicate, you need to increase the delay in the loop, and also exit the l variable in the loop problem

 loopThroughSplittedText: function (splittedText) { splittedText.forEach(function (text, i) { setTimeout(function () { console.log(text); }, i * 1000) }) } 

 var obj = { loopThroughSplittedText: function(splittedText) { splittedText.forEach(function(text, i) { setTimeout(function() { document.getElementById('x').innerHTML += text }, i * 1000) }) } } obj.loopThroughSplittedText('abcde'.split('')) 
 <div id="x"></div> 
+2
source

A recursive function call will complete the task:

 var a = [ 1,2,3,4,5,6,7,8,9,10 ]; function log(i){ console.log(a[i]); if (i<a.length){ setTimeout(function(){ i++; log(i); },1000); } } log(0); 

http://jsfiddle.net/Curt/rjve4whe/1/

+2
source

Another solution: setInterval:

 var i = 0; var intv = setInterval(function() { if (i >= splittedText.length) { clearInterval(intv); } else { console.log(splittedText[i]); ++i; } }, 1000); 
+1
source

There are a couple of issues here.

  • setTimeout should accept a function, not the result of a function call
  • setTimeout returns immediately, so all the actions in your loop will be launched at about the same moment, and everyone will wait 1000 ms before using them (despite the above comment, which means that they are all executed at the same moment).
  • The value of i will be equal to splittedText.length for each iteration due to the fact that you do not exchange your loop control variable in closure.

What you need to do is wait for the setTimeout statements to execute before moving on to the next iteration of the loop.

For instance:

 var splittedText = ["Hello", "World", "How", "Are", "You", "Today"]; function loopThroughSplittedText(splittedText) { displayValue(splittedText,0); } function displayValue(arr, i){ if(i<arr.length){ setTimeout(function(){ document.getElementById('text').innerHTML = arr[i]; console.log(arr[i]) displayValue(arr,i+1); },1000) } } loopThroughSplittedText(splittedText) 

Real-time example: http://jsfiddle.net/d3whkjww/1/

+1
source

It will also work

  function loopThroughSplittedText(splittedText) { for (var i=0; i < splittedText.length;i++) { (function(ind, text) { setTimeout(function(){console.log(text);}, 1000 + (1000 * ind)); })(i, splittedText[i]); } } 
+1
source

The output of an alternative solution to the problem that uses the third argument to setTimeout , which is only supported in new browsers :

 (function (splittedText) { for (var i = 0; i < splittedText.length; i++) { setTimeout( function(val) { console.log(val); }, i * 1000, splittedText[i] ); } })(["Hello", "world", "!"]); 

The API documentation may be here (note the optional parameters).

+1
source

One more example:

 var split = 'Lorem ipsum dolor'.split(' '); var loop = function() { console.log(split[0]); split = split.slice(1); if (split.length > 0) { setTimeout(function() { loop(); }, 1000); } } loop(); 
+1
source

Most likely, you will want to use a recursive function instead of a for loop here. However, I will explain both ways just in case you (or someone else reading this) set your heart to it with a loop.

For a recursive function, the general idea is that you want to call the function once and then let it call itself repeatedly until it finishes doing what you want. As for the code, it might look something like this:

 loopThroughSplittedText: function(splittedText) { // Create our counter; delayedOutput will use this to // track how far along in our string we are currently at var locationInString = 0; function delayedOutput() { // Output the next letter in our string console.log(splittedText[locationInString]); // Increment our counter so that on the next call we are on the next letter locationInString++; // Only perform setTimeout if we still have text left to output if (locationInString < splittedText.length) { // Functions can reference themselves using their own name setTimeout(delayedOutput, 1000); } } // Call our function once to get things started delayedOutput(); }, 

Alternatively, if you really prefer to use a loop, you can still do it, but there is an honest battle that needs to be done for this.

First, you will need to place console.log in your own function. This is because when you place console.log(something) , you do not actually pass it on, but call it right then and there, which you don’t want; Having called him, he directly splashes out the text on the console, but does not wait later. Dropping it in its own function, it can be passed to setTimeout so that it can be called later.

Secondly, you will have to transfer this function to another function in order to ensure its correct value i when it starts. The reason is that it is true: your intention is to tell the function "when you are ready, use what i was when I set you up." However, what you are doing right now effectively says, “When you are ready, look i .” Since the function does not verify that i , until it is ready to run, it will not know its value until you complete the cycle, and the value of i will be much larger than you want!

As part of the subitem above, you should call this function immediately. This is called a direct function call. If you are not familiar with them, they certainly deserve attention. Their use is a little unusual, but they are a powerful tool in the right place.

Finally, since you are setting everything right here and now, you want to make sure that the timeout for each function is divided into the second part; as now, you say, “do all these seconds from now on,” when your intention is “do all these two seconds, starting from one second.” This fix is ​​relatively simple; all you have to do is multiply your timeout by i so that you set the first one to go after 1 second and the second after 2 seconds, etc.

All of this together gives a code that looks something like this:

 loopThroughSplittedText: function(splittedText) { for (var i = 0; i < splittedText.length; i++) { setTimeout( (function(locationInString) { return function() { console.log(splittedText[locationInString]); }; }(i)), (1000*i) ); } }, 

As for a better solution, I would probably recommend a recursive function. The recursive version will only create one function that calls itself for each line you pass, while the loop version for the cycle will create one function for each character in the line, which can quickly get out of hand. Creating a function (and creating an object as a whole) can become expensive in JavaScript when you work on larger projects, so it’s best to use solutions that avoid a huge number of functions when possible.

But still, for the sake of explanation, I would not want to leave you without a for loop version; knowledge may come in handy in other places. :)

+1
source

using closure https://jsfiddle.net/x3azn/pan2oc9y/4/

 function loopThroughSplittedText(splittedText) { var splittedText = ["Hello", "World", "How", "Are", "You", "Today"]; for (var i = 0; i < splittedText.length; i++) { // for each iteration console.log a word // and make a pause after it (function(_i) { setTimeout(function() { window.document.getElementById('text').innerHTML = splittedText[_i]; console.log(splittedText[_i]); }, 1000) }(i)); } } loopThroughSplittedText() 
+1
source

Source: https://habr.com/ru/post/989207/


All Articles