我需要在1秒钟内执行3个功能。
为简单起见,这些功能是:
console.log('1');
console.log('2');
console.log('3');
我能做到这一点:(非常难看)
console.log('1')
setTimeout(function () {
setTimeout(function () {
console.log('2')
setTimeout(function () {
console.log('3')
}, 1000)
}, 1000)
}, 1000)
或者我可以创建array
个函数,并将setInterval
与global
计数器一起使用。
有没有优雅的方式吗?
(p.s。函数2不依赖于函数编号1 ...因此 - 每秒执行下一个函数。)。
答案 0 :(得分:13)
您可以使用setTimeout
:
var funcs = [func1, func2, func3],
i = 0;
function callFuncs() {
funcs[i++]();
if (i < funcs.length) setTimeout(callFuncs, 1000);
}
setTimeout(callFuncs, 1000); //delay start 1 sec.
或者直接调用callFuncs()开始。
<强>更新强>
setInterval
方法(注意堆叠通话的风险):
var funcs = [func1, func2, func3],
i = 0,
timer = setInterval(callFuncs, 1000);
function callFuncs() {
funcs[i++]();
if (i === funcs.length) clearInterval(timer);
}
答案 1 :(得分:9)
假设您在现代浏览器上运行它或添加了对array.map的支持,这非常简洁:
[func1, func2, func3].map(function (fun, index) {
setTimeout(fun, 1000 + index * 1000);
}
答案 2 :(得分:3)
setTimeout(function(){console.log('1')}, 1000);
setTimeout(function(){console.log('2')}, 2000);
setTimeout(function(){console.log('3')}, 3000);
答案 3 :(得分:1)
我认为最简单的方法是在函数中创建一些闭包
首先我要回忆一下,你对使用setInterval
很感兴趣,因为setTimeout
的开销可能会触发10毫秒的目标。因此,特别是如果使用短(<50ms)间隔,则更喜欢setInterval。
所以我们需要存储函数数组,最新执行函数的索引以及停止调用的间隔引用。
function chainLaunch(funcArray, time_ms) {
if (!funcArray || !funcArray.length) return;
var fi = 0; // function index
var callFunction = function () {
funcArray[fi++]();
if (fi==funcArray.length)
clearInterval(chainInterval);
} ;
var chainInterval = setInterval( callFunction, time_ms);
}
Rq:你可能想要复制函数数组(funcArray = funcArray.slice(0);
)
Rq2:你可能想在数组中循环
Rq3:你可能想接受chainlaunch的附加参数。使用var funcArgs = arguments.slice(3);
检索它们并在函数上使用apply:funcArray[fi++].apply(this,funcArgs);
无论如何,以下测试有效:
var f1 = function() { console.log('1'); };
var f2 = function() { console.log('2'); };
var f3 = function() { console.log('3'); };
var fArr = [f1, f2, f3];
chainLaunch(fArr, 1000);
正如你在这个小提琴中看到的那样:http://jsfiddle.net/F9UJv/1/ (打开控制台)
答案 4 :(得分:1)
在es6中有一种称为生成器的新类型的函数声明(a.k.a ecmascript 6,es2015)。它对这种情况非常有用,并使您的异步代码看起来是同步的。 es6是2015年最新的JavaScript标准。它适用于现代浏览器,但您现在可以使用Babel及其javascript polyfill来使用生成器,即使在较旧的浏览器上也是如此。
Here是关于生成器的教程。
下面的函数myDelayedMessages是一个生成器的示例。 Run是一个辅助函数,它接受一个它调用的生成器函数,并提供一个函数来推动生成器作为它调用的生成器函数的第一个参数。
function delay(time, callback) {
setTimeout(function () {
callback();
}, time);
}
function run(generatorFunction) {
var generatorItr = generatorFunction(resume);
function resume(callbackValue) {
generatorItr.next(callbackValue);
}
generatorItr.next()
}
run(function* myDelayedMessages(resume) {
for(var i = 1; i <= 3; ++i) {
yield delay(1000, resume);
console.log(i);
}
});
这是代码的概述,类似于上面教程的最终概述。
run
接受我们的生成器并创建一个恢复功能。运行创建一个
生成器 - 迭代器对象(接下来调用的东西),提供
恢复。 答案 5 :(得分:0)
这里有两种方法。一个是setTimeout,另一个是setInterval。在我看来,第一个更好。
for(var i = 1; i++; i<=3) {
setTimeout(function() {
console.log(i);
}, 1000*i);
}
// second choice:
var i = 0;
var nt = setInterval(function() {
if(i == 0) return i++;
console.log(i++);
if(i>=3) clearInterval(nt);
}, 1000);