用forEach循环执行每个迭代之后添加一个延迟 [英] Add a delay after executing each iteration with forEach loop
问题描述
var items = document.querySelector('。item');
items.forEach(function(el){
//在下一个el之前做一些事情并暂停;
});
c $ c> Array#forEach —尽管以不同的方式你可能会想到它。你可以不是做这样的事情:
$ b
var array = ['some','array','contains','words'];
array.forEach(function(el){
console.log(el);
wait(1000); //等待1000毫秒
});
console.log('Loop finished。');
...并获得输出:
一些
数组//一秒钟后
包含//两秒钟后
字//三秒钟后
循环结束。 //四秒钟之后
没有同步 wait
或 sleep
在JavaScript中阻止所有代码。
延迟JavaScript处于非阻塞状态。这意味着使用 setTimeout
或其亲属之一。我们可以使用我们传递给函数的第二个参数 Array#forEach
:它包含当前元素的索引:
index
,我们可以计算函数何时执行。但是现在我们遇到了一个不同的问题: console.log('Loop finished。')
在循环的第一次迭代之前执行。这是因为 setTimout
是非 - ndash; block。
JavaScript设置循环中的超时,但不会等待超时完成。它只是在 forEach
之后继续执行代码。
无极
秒。让我们建立一个承诺链:
var array = ['some','数组','包含','文字']; var interval = 1000; //两次迭代之间的延迟时间应该是多少(毫秒)?var promise = Promise.resolve(); array.forEach(function(el){promise = promise.then(function(){console.log(el ); return new Promise(function(resolve){setTimeout(resolve,interval);});});}); promise.then(function(){console.log('Loop finished。');}); / code>
有一篇关于 Promise
s连同 forEach
/ map
/ 过滤器
here 。
如果数组可以动态更改,我会变得更复杂。在这种情况下,我不认为应该使用 Array#forEach
。试试看:
$ b
var array = ['一些,数组,含有,文字]; var interval = 2000; //两次迭代之间的延迟时间应该是多少(毫秒)?var loop = function(){return new Promise(function(outerResolve){var promise = Promise.resolve(); var i = 0; var next =函数(){var el = array [i]; //你的代码在这里console.log(el); if(++ i< array.length){promise = promise.then(function(){return new Promise函数(解析){setTimeout(函数(){解析();下一步();},间隔);});});}其他{setTimeout(outerResolve,间隔); / /或只是调用outerResolve ();}();}}; var input = document添加新项目到数组中array.push(input.value); input.value ='add()'); document.querySelector('button')。addEventListener('click',function ';});
< input type =text >< button>添加到数组< / button>
Is there an easy way to slow down the iteration in a forEach (with plain javascript)? For example:
var items = document.querySelector('.item');
items.forEach(function(el) {
// do stuff with el and pause before the next el;
});
What you want to achieve is totally possible with Array#forEach
— although in a different way you might think of it. You can not do a thing like this:
var array = ['some', 'array', 'containing', 'words'];
array.forEach(function (el) {
console.log(el);
wait(1000); // wait 1000 milliseconds
});
console.log('Loop finished.');
... and get the output:
some
array // one second later
containing // two seconds later
words // three seconds later
Loop finished. // four seconds later
There is no synchronous wait
or sleep
function in JavaScript that blocks all code after it.
The only way to delay something in JavaScript is in a non–blocking way. That means using setTimeout
or one of its relatives. We can use the second parameter of the function that we pass to Array#forEach
: it contains the index of the current element:
var array = ['some', 'array', 'containing', 'words'];
var interval = 1000; // how much time should the delay between two iterations be (in milliseconds)?
array.forEach(function (el, index) {
setTimeout(function () {
console.log(el);
}, index * interval);
});
console.log('Loop finished.');
Using the index
, we can compute when the function should be executed. But now we have a different problem: the console.log('Loop finished.')
is executed before the first iteration of the loop. That's because setTimout
is non–blocking.
JavaScript sets the timeouts in the loop, but it doesn't wait for the timeouts to complete. It just continues executing the code after the forEach
.
To handle that, we can use Promise
s. Let's build a promise chain:
var array = ['some', 'array', 'containing', 'words'];
var interval = 1000; // how much time should the delay between two iterations be (in milliseconds)?
var promise = Promise.resolve();
array.forEach(function (el) {
promise = promise.then(function () {
console.log(el);
return new Promise(function (resolve) {
setTimeout(resolve, interval);
});
});
});
promise.then(function () {
console.log('Loop finished.');
});
There is an excellent article about Promise
s in conjunction with forEach
/map
/filter
here.
I gets trickier if the array can change dynamically. In that case, I don't think Array#forEach
should be used. Try this out instead:
var array = ['some', 'array', 'containing', 'words'];
var interval = 2000; // how much time should the delay between two iterations be (in milliseconds)?
var loop = function () {
return new Promise(function (outerResolve) {
var promise = Promise.resolve();
var i = 0;
var next = function () {
var el = array[i];
// your code here
console.log(el);
if (++i < array.length) {
promise = promise.then(function () {
return new Promise(function (resolve) {
setTimeout(function () {
resolve();
next();
}, interval);
});
});
} else {
setTimeout(outerResolve, interval);
// or just call outerResolve() if you don't want to wait after the last element
}
};
next();
});
};
loop().then(function () {
console.log('Loop finished.');
});
var input = document.querySelector('input');
document.querySelector('button').addEventListener('click', function () {
// add the new item to the array
array.push(input.value);
input.value = '';
});
<input type="text">
<button>Add to array</button>
这篇关于用forEach循环执行每个迭代之后添加一个延迟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!