I have a asynchronous function that I want to have a 5000ms delay before being fired. I am trying to use setTimeout() to achieve this. This async function occurs in a loop that runs several times, with the async function being passed different data each time, thus setInterval() cannot be used here.
Problem: The async function gets triggered instantly without delay (console prints 5 Done messages instantly` and loops without any delay. What happened, and how can I solve it?
Javascript Code
someFunction(listings, function() {
    for (var i in listings ) {
        var listing = listings[i];
        setTimeout(asyncFunction(listing, function(data) {
            console.log('Done');
        }), 5000);
    }
});
                You have to wrap the function in another function. Currently, you're invoking the function, and passing the return value as an argument to setTimeout. The code below will (correctly) pass a function to setTimeout. After 5 seconds, the function executes.
I had to add two functions to achieve the desired behaviour, because of scoping issues. After 5 seconds, the loop has already finished, and the listing variable would be equal to the last element in listings.
someFunction(listings, function() {
    var counter = 0;  // Define counter for 5 second-delays between each call
    for (var i in listings ) {
        var listing = listings[i];
        (function(listing){ //Closure function
            setTimeout(function(){ //setTimeout function
                // Because of the closure, `listing` is unique
                asyncFunction(listing, function(a, b) {
                    console.log('Done');
                });
            }, 5000 * ++counter); //Increase counter for each loop
        })(listing);
    }
});
                        If you are using ECMAScript6 you can use Promise.
So create a delay function that wrap the call to the setTimeout into a Promise:
function delay(ms) {
    return new Promise(function (resolve) { return setTimeout(resolve, ms); });
};
And you can use it like that :
someFunction(listings, function() {
    for (var i in listings ) {
        var listing = listings[i];
        delay(5000).then(() => {
            return asyncFunction(listing);
        }).then(() => {
            console.log('Done');
        });
    }
});
If you are using ECMAScript 2017 you can use aync/await.
Async functions return promise so you don't have to change the code of the delay function.
async someFunction(listings, function() {
    for (var i in listings ) {
        var listing = listings[i];
        await delay(5000);
        await asyncFunction(listing);
        console.log('Done');
    }
});
                        Not knowing what your asyncFunction does, it would seem that it could simply return the function you passed it.
someFunction(listings, function() {
    for (var i = 0; i < listings.length; ++i ) {
        setTimeout(asyncFunction(listings[i], function(data) {
            console.log('Done');
        }), 5000 * i);
    }
});
function asyncFunction( lstng, func ) {
    return func;
}
Though I'd expect that you need to wrap up some additional logic.
function asyncFunction( lstng, func ) { 
    return function() {
        // do some stuff with the listing
        //   then invoke the func
        func();
    }
}
Now your asyncFunction wraps whatever is needed in a new function that is returned to the setTimeout. The new function also invokes the callback you passed.
JSFIDDLE DEMO
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With