我有一个异步函数,我希望在被触发之前有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);
}
});
答案 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
的新函数所需的所有内容。新函数还会调用您传递的回调。
答案 3 :(得分:-1)
这是区别。关键点是asyncFunction
做什么?你能把它粘贴出来吗?
var foo=function(){
alert("BAR");
return function(){
alert("I AM!");
};
}
setTimeout(foo(),4000);
setTimeout(foo,5000);