假设我想运行多个计时器函数,一个接着一个,即首先一个函数运行 5 分钟,然后在第一个倒计时完成后,另一个计时器开始再运行 2 分钟。
我实现了定时器功能如下
function timer(count) {
console.log(count)
let counter = setInterval(() => {
count = count - 1;
if (count < 0) {
clearInterval(counter);
return;
}
console.log(count)
}, 1000);
}
然后当我使用不同的参数调用这个函数两次时
timer(15);
timer(5);
我得到的输出为
15
5
14
4
13
3
11
1
10
0
9
8
.
.
0
但是我想要的输出是
15
14
.
.
2
1
0
5
4
3
2
1
0
最佳答案
问题是您的timer
函数立即启动计时器。计时器是异步的,因此当您调用它两次时,您只需立即启动两个计时器并且它们并行运行。
如果您希望在完成后发生某些事情,那么您必须明确地说出来。您有两个选择:
回调
这是处理异步代码的稍微“旧”的风格。您调用一个稍后执行某些操作的函数,然后为其提供一个函数作为参数,指示完成后要执行的操作:
function timer(count, callback = () => {}) { //<-- take callback
//if callback is not supplied, it's going to be an empty function
console.log(count)
let counter = setInterval(() => {
count = count - 1;
if (count < 0) {
clearInterval(counter);
callback(); //<-- run callback after this timer is finished
return;
}
console.log(count)
}, 1000);
}
//run a timer for 15 then a timer for 5
timer(15, () => timer(5));
这有效,但过度使用回调可能会导致所谓的 callback hell 。这里的例子也很容易出现这种情况,例如,如果您想运行一个计时器 5,然后是 4,然后是 3,然后是 2,然后是 1,您最终会得到这样的结果:
timer(5,
() => timer(4,
() => timer(3,
() => timer(2,
() => timer(1)
)
)
)
);
或者一行(为了好玩):
timer(5, () => timer(4, () => timer(3, () => timer(2, () => timer(1)))));
promise
Promises是处理异步操作的更新方法,有助于保持代码简洁。
function timer(count) {
console.log(count)
return new Promise(resolve => { //return a Promise
let counter = setInterval(() => {
count = count - 1;
if (count < 0) {
clearInterval(counter);
resolve(); //it is resolved when the count finishes
return;
}
console.log(count)
}, 1000);
});
}
//run a timer for 15 then a timer for 5
timer(15)
.then(() => timer(5));
Promises 帮助解决的一件事是回调 hell ,现在如果你想运行一个计时器 5,然后是 4,然后是 3,然后是 2,然后是 1,你会得到一个更合理的代码:
timer(5)
.then(() => timer(4))
.then(() => timer(3))
.then(() => timer(2))
.then(() => timer(1));
不再嵌套。
异步/等待
这实际上又是Promise。不过是乔装打扮而已。如果函数返回 Promise,您可以 await
它等待 Promise 被解析,然后执行下一行代码。您只能在 async
函数中使用 await
,但是,由于 await
实际上在幕后将您的代码转换为 Promise。从功能上讲,没有什么区别,但您可以以不同的方式构建代码:
function timer(count) {
console.log(count)
return new Promise(resolve => { //return a Promise
let counter = setInterval(() => {
count = count - 1;
if (count < 0) {
clearInterval(counter);
resolve(); //it is resolved when the count finishes
return;
}
console.log(count)
}, 1000);
});
}
//run a timer for 15 then a timer for 5
async function main() { //you can only use `await` in async funcions
await timer(15);
await timer(5);
}
/* the above will actually be transformed behind the scenes into:
timer(15)
.then(() => timer(5));
*/
main();
关于javascript - 如何在vanilla javascript中一个接一个地运行多个计时器函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59628791/