异步函数的setTimeout

时间:2011-11-26 14:19:37

标签: javascript jquery

我有一个异步函数,我希望在被触发之前有5000ms的延迟。我正在尝试使用setTimeout()来实现这一目标。此异步函数发生在多次运行的循环中,异步函数每次都传递不同的数据,因此setInterval()不能在这里使用。

问题:异步功能立即被触发而没有延迟(控制台立即打印5 Done条消息并且没有任何延迟地循环。发生了什么,我该如何解决?

Javascript代码

someFunction(listings, function() {
    for (var i in listings ) {
        var listing = listings[i];
        setTimeout(asyncFunction(listing, function(data) {
            console.log('Done');
        }), 5000);
    }
});

4 个答案:

答案 0 :(得分:11)

您必须将该函数包装在另一个函数中。目前,您正在调用该函数,并将返回值作为参数传递给setTimeout。下面的代码将(正确地)将函数传递给setTimeout。 5秒后,该函数执行。

由于范围问题,我不得不添加两个函数来实现所需的行为。 5秒后,循环已经完成,listing变量将等于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);
    }
});

答案 1 :(得分:5)

如果您使用的是ECMAScript6,则可以使用Promise

因此,创建一个延迟函数,将对setTimeout的调用包装成Promise:

import sys
from time import strftime
import IPython

# Custom IO class for file logging
class StdinLogger (object):
    def __init__(self, wrapped, file):
        # double-underscore everything to prevent clashes with names of
        # attributes on the wrapped stream object.
        self.__wrapped = wrapped
        self.__file = file

    def __getattr__(self, name):
        return getattr(self.__wrapped, name)

    def readline(self):
        str = self.__wrapped.readline()
        self.__file.write(str)
        self.__file.flush()
        return str


# Custom IO class for file logging
class StdoutLogger (object):
    def __init__(self, wrapped, file):
        # double-underscore everything to prevent clashes with names of
        # attributes on the wrapped stream object.
        self.__wrapped = wrapped
        self.__file = file

    def __getattr__(self, item):
        return getattr(self.__wrapped, item)

    def write(self, str):
        self.__file.write(str)
        self.__file.flush()
        self.__wrapped.write(str)
        self.__wrapped.flush()


f = open("LOG-" + strftime("%Y-%m-%d-%H-%M-%S") + ".txt", 'w')
# Initialize the file logger
sys.stdin = StdinLogger(sys.stdin, f)
sys.stdout = StdoutLogger(sys.stdout, f)


# Embed IPython shell
IPython.embed(banner1="", banner2="")

你可以这样使用它:

function delay(ms) {
    return new Promise(function (resolve) { return setTimeout(resolve, ms); });
};

如果您使用的是ECMAScript 2017,则可以使用aync/await

异步函数返回promise,因此您不必更改延迟函数的代码。

someFunction(listings, function() {
    for (var i in listings ) {
        var listing = listings[i];
        delay(5000).then(() => {
            return asyncFunction(listing);
        }).then(() => {
            console.log('Done');
        });
    }
});

答案 2 :(得分:1)

不知道你的asyncFunction做了什么,它似乎只能返回你传递给它的函数。

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;
}

虽然我希望你需要结束一些额外的逻辑。

function asyncFunction( lstng, func ) { 
    return function() {
        // do some stuff with the listing

        //   then invoke the func
        func();
    }
}

现在你的asyncFunction包含了返回setTimeout的新函数所需的所有内容。新函数还会调用您传递的回调。


JSFIDDLE DEMO

答案 3 :(得分:-1)

这是区别。关键点是asyncFunction做什么?你能把它粘贴出来吗?

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