Issue
New to js,I want to output 5 ‘!’s with a 1-second interval,and finally output "end".
I thought the problem was related to asynchronization.
I have tried a lot of times and a lot of methods such as "await,async" and "promise" ,but still failed.
class A {
constructor() {
this.cnt = 5;
}
real() {
this.cnt--;
console.log("!");
}
getCnt() {
return this.cnt;
}
}
class B {
constructor() {
this.a = new A();
}
fun() {
if (this.a.getCnt() > 0) {
this.a.real();
setTimeout(() => this.fun(), 1000);
}
}
}
class C {
constructor() {
this.b = new B();
}
f() {
this.b.fun();
console.log("end");
}
}
var c = new C();
c.f();
Solution
Skipping the complexity of the 3 classes involved, this is elegantly solved with async
functions. (Without async functions, the cascade of setTimeout
s in a loop becomes more difficult to manage.)
This can of course be wrapped into a trio of classes if required.
// Turns `setTimeout` into a promise you can `await`.
async function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// Calls a function `fun` `times` times, delaying for `delayTime` ms between each invocation.
// Since this is an async function, it returns a promise that will resolve as soon as it's done,
// which in turn can be awaited upon.
async function repeatWithDelay(fun, times, delayTime) {
for (let i = 0; i < times; i++) {
await fun(i);
await delay(delayTime);
}
}
// Prints the number passed in (could just print an exclamation mark).
function print(i) {
console.log(`${i}!`);
}
async function main() {
console.log("Go!");
await repeatWithDelay(print, 5, 500);
console.log("Done!");
}
// Assumes top-level `await` is not available in your environment.
// If it is, this too can be replaced with a simple `await`.
main().then(() => {
console.log("Main done.");
});
This prints out
Go!
0!
1!
2!
3!
4!
Done!
Main done.
Answered By – AKX
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0