Skip to content

Instantly share code, notes, and snippets.

@fernandosavio
Last active May 30, 2022 06:44
Show Gist options
  • Save fernandosavio/6011834 to your computer and use it in GitHub Desktop.
Save fernandosavio/6011834 to your computer and use it in GitHub Desktop.
An Array forEach with a delay between steps.
/**
* An array forEach with a delay between steps.
*
* @param {Function} callback Function to execute for each element. It receives three arguments, the element value, the element index and the array being traversed, respectivily.
* @param {Number} timeout Number of milliseconds that the function call should be delayed by.
* @param {Object} thisArg Object to use as this when executing callback.
* @this {Array}
* @return {undefined}
*/
Array.prototype.delayedForEach = function(callback, timeout, thisArg){
var i = 0,
l = this.length,
self = this,
caller = function(){
callback.call(thisArg || self, self[i], i, self);
(++i < l) && setTimeout(caller, timeout);
};
caller();
};
/*
=== Usage ===
var numbers = [100, 2,"abc", 4, true];
numbers.delayedForEach(function(elem, index, array){
console.log("this = " + this);
console.log("elem = " + elem);
console.log("index = " + index);
console.log("array = " + array);
}, 1000);
var myScope = {foo: "bar"};
numbers.delayedForEach(function(){ console.log(this); }, 1000, myScope);
*/
@tebs1200
Copy link

I needed a variation that took a completion handler that executes after all the iterations:

Array.prototype.delayedForEach = function(callback, timeout, thisArg, done){
    var i = 0,
        l = this.length,
        self = this;

    var caller = function() {
        callback.call(thisArg || self, self[i], i, self);
        if(++i < l) {
            setTimeout(caller, timeout);
        } else if(done) {
            setTimeout(done, timeout);
        }
    };

    caller();
};

/*
=== Usage ===

let testArray = [1,2,3,4];

testArray.delayedForEach(function(num) {
    console.log(num);
}, 1000, null, function() {
    console.log("done!");
});

*/

@valeriosillari
Copy link

Nice! I am struggling with loops.

One question: assuming your array would be more bigger (with 200 hundred items) and it wil take lo of time for be completed, i am trying to stop the loop if an event occurs (user click a button for example)

Do you have any tip/ suggestion for it? :)

@fernandosavio
Copy link
Author

Sorry @valeriosillari, you probably don't need it anymore... But for future reference: setTimeout returns a identifier of the timer it creates, so you can cancel it with clearTimeout.

Ex:

let timerID = setTimeout(() => console.log('not gonna print'), 10000)
clearTimeout(timerID)
// prints nothing because the timer war cancelled before executed

@harsilspatel
Copy link

harsilspatel commented Oct 6, 2018

Alternatively, we can also use setTimeout()

const INTERVAL = 1000;	// in milliseconds
yourArray.forEach((item, index) => {
	setTimeout(() => {
		console.log(item);
	}, INTERVAL*index);
});

@iszlailorand
Copy link

@harsilspatel ... did you run your code?

@harsilspatel
Copy link

Hi @iszlailorand,

Yes, I just (re-)tested my code against the delayedForEach (from the gist) and it works just fine! I'm guessing you're having issues running my code? Feel free to post your snippet here and I'll try to help you out :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment