简体   繁体   中英

Exit while loop in async method in OOP Javascript ES6

My class has a method that does something like this:

async foo(..., callback){
    do{
        for(...){
            await bar1();
            await bar2();
        }
    }
    while(...);
    callback();
}

I want to be able to interrupt the loop on command, so this was my approach at it:

async foo(..., callback){
    this.stop = false; // Reset the property
    do{
        for(...){
            await bar1();
            await bar2();
        }
    }
    while(!this.stop && ...);
    callback();
}

stopTheLoop(){
    this.stop = true;
}

And it looked fine to me. So I test it like:

myObject.foo(..., () => {
    console.log("Finished!");
});
console.log("Async test");
setTimeout(() => {
    myObject.stopTheLoop();
}, 1000);

The behaviour is that i see printed "Async test", which means that the foo() call is correcrly not blocking code execution on the main thread, so i think it's safe to say that the setTimeout function gets called. But the do-while loop never ends, and i never see my "Finished!" callback.

I might not have fully understood async/await in ES6, what am I missing?

bar1 and bar2 appear not to return promises that actually wait for anything. await ing a plain value is equivalent to Promise.resolve().then(…) , which will by asynchronous enough to continue with console.log("Async test"); but otherwise goes into a loop of running promise tasks, not allowing timeouts and other macro tasks to interrupt it. this.stop never changes because the timeout callback never gets a chance to run. Have a look at What determines the call order of deferred function using promises or setTimeout? and Difference between microtask and macrotask within an event loop context for details.

You can fix this by putting a short actual timeout in your loop to make it asynchronous:

async foo(…) {
    this.stop = false; // Reset the property
    do {
        for(…) {
            bar1();
            bar2();
            await new Promise(resolve => setImmediate(resolve));
        }
    } while (!this.stop && …);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM