简体   繁体   中英

setTimeout on Asynchronous function

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

it's the difference.the key point is what is asyncFunction do? can you paste it out?

var foo=function(){
    alert("BAR");
    return function(){
        alert("I AM!");
    };
}
setTimeout(foo(),4000);
setTimeout(foo,5000);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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