如何让setTimeout中的函数完整执行?
How can I make the function in setTimeout execute completely?
初学js,想输出5个'!',间隔1秒,最后输出"end"。
我认为问题与异步有关。
我尝试了很多次,尝试了很多方法,比如“await,async”和“promise”,但还是失败了。
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();
跳过涉及的 3 个 类 的复杂性,这可以用 async
函数优雅地解决。 (没有异步函数,循环中 setTimeout
的级联变得更难管理。)
如果需要,这当然可以包装成三个 类。
// 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.");
});
这会打印出来
Go!
0!
1!
2!
3!
4!
Done!
Main done.
最后,您需要让您的方法 fun
能够在完成时报告,因为它是一个异步方法(调用 setTimeout
)。最好的方法是 return a Promise
允许调用在其上使用 await
fun() {
return new Promise(resolve => {
const exec = () => {
if (this.a.getCnt() > 0) {
this.a.real();
setTimeout(exec.bind(this), 1000);
}
else{
resolve();
}
}
exec.apply(this);
})
}
完成后,还将函数 f
标记为 async
,这样您就可以在其中调用 await
:
async f() {
await this.b.fun();
console.log("end");
}
然后一切按预期工作:
class A {
constructor() {
this.cnt = 5;
}
real() {
this.cnt--;
console.log("!");
}
getCnt() {
return this.cnt;
}
}
class B {
constructor() {
this.a = new A();
}
fun() {
return new Promise(resolve => {
const exec = () => {
if (this.a.getCnt() > 0) {
this.a.real();
setTimeout(exec.bind(this), 1000);
}
else{
resolve();
}
}
exec.apply(this);
})
}
}
class C {
constructor() {
this.b = new B();
}
async f() {
await this.b.fun();
console.log("end");
}
}
var c = new C();
c.f();
我尝试编写一个模拟输入的通用函数,希望这能帮助您理解 async/await 函数
let fakeConsole = document.getElementById('console');
async function sleep(time) {
await new Promise(r => setTimeout(r, time));
}
function type(text) {
fakeConsole.innerHTML += text;
}
async function emulateTyping(text, speed) {
// split the text into an array of characters;
const characters = text.split('').reverse();
if (characters.length > 0) {
// display first character right away
type(characters.pop());
while (characters.length > 0) {
// wait <speed> millisections
await sleep(speed);
// type one character
type(characters.pop());
}
}
}
async function main() {
// async function we wait for the end with "await"
await emulateTyping("!!!!!", 500);
// sync function
type(' END');
};
main();
<pre id="console"></pre>
如果使用 promise,那么你也需要解析 setTimeout
中的响应
class A {
constructor() {
this.cnt = 5;
}
real() {
this.cnt--;
console.log("!");
}
getCnt() {
return this.cnt;
}
}
class B {
constructor() {
this.a = new A();
}
fun() {
return new Promise((resolve) => {
if (this.a.getCnt() > 0) {
this.a.real();
setTimeout(() => resolve(this.fun()), 1000);
} else {
resolve()
}
})
}
}
class C {
constructor() {
this.b = new B();
}
f() {
this.b.fun().then(() => {
console.log("end");
})
}
}
var c = new C();
c.f();
对于多个循环:
var loop = [array of 100 items];
await Promise.all(
loop.map(async (item) => await this.b.fun();)
)
console.log("end");
初学js,想输出5个'!',间隔1秒,最后输出"end"。 我认为问题与异步有关。 我尝试了很多次,尝试了很多方法,比如“await,async”和“promise”,但还是失败了。
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();
跳过涉及的 3 个 类 的复杂性,这可以用 async
函数优雅地解决。 (没有异步函数,循环中 setTimeout
的级联变得更难管理。)
如果需要,这当然可以包装成三个 类。
// 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.");
});
这会打印出来
Go!
0!
1!
2!
3!
4!
Done!
Main done.
最后,您需要让您的方法 fun
能够在完成时报告,因为它是一个异步方法(调用 setTimeout
)。最好的方法是 return a Promise
允许调用在其上使用 await
fun() {
return new Promise(resolve => {
const exec = () => {
if (this.a.getCnt() > 0) {
this.a.real();
setTimeout(exec.bind(this), 1000);
}
else{
resolve();
}
}
exec.apply(this);
})
}
完成后,还将函数 f
标记为 async
,这样您就可以在其中调用 await
:
async f() {
await this.b.fun();
console.log("end");
}
然后一切按预期工作:
class A {
constructor() {
this.cnt = 5;
}
real() {
this.cnt--;
console.log("!");
}
getCnt() {
return this.cnt;
}
}
class B {
constructor() {
this.a = new A();
}
fun() {
return new Promise(resolve => {
const exec = () => {
if (this.a.getCnt() > 0) {
this.a.real();
setTimeout(exec.bind(this), 1000);
}
else{
resolve();
}
}
exec.apply(this);
})
}
}
class C {
constructor() {
this.b = new B();
}
async f() {
await this.b.fun();
console.log("end");
}
}
var c = new C();
c.f();
我尝试编写一个模拟输入的通用函数,希望这能帮助您理解 async/await 函数
let fakeConsole = document.getElementById('console');
async function sleep(time) {
await new Promise(r => setTimeout(r, time));
}
function type(text) {
fakeConsole.innerHTML += text;
}
async function emulateTyping(text, speed) {
// split the text into an array of characters;
const characters = text.split('').reverse();
if (characters.length > 0) {
// display first character right away
type(characters.pop());
while (characters.length > 0) {
// wait <speed> millisections
await sleep(speed);
// type one character
type(characters.pop());
}
}
}
async function main() {
// async function we wait for the end with "await"
await emulateTyping("!!!!!", 500);
// sync function
type(' END');
};
main();
<pre id="console"></pre>
如果使用 promise,那么你也需要解析 setTimeout
中的响应
class A {
constructor() {
this.cnt = 5;
}
real() {
this.cnt--;
console.log("!");
}
getCnt() {
return this.cnt;
}
}
class B {
constructor() {
this.a = new A();
}
fun() {
return new Promise((resolve) => {
if (this.a.getCnt() > 0) {
this.a.real();
setTimeout(() => resolve(this.fun()), 1000);
} else {
resolve()
}
})
}
}
class C {
constructor() {
this.b = new B();
}
f() {
this.b.fun().then(() => {
console.log("end");
})
}
}
var c = new C();
c.f();
对于多个循环:
var loop = [array of 100 items];
await Promise.all(
loop.map(async (item) => await this.b.fun();)
)
console.log("end");