0

I'm trying to delete a bunch of temp files that were created during a dispose function in a Visual Studio Code extension. For some reason a forEach that initiates a bunch of async work is returning before that work is done even though I have await in front of it. Is my problem with the understanding of forEach, await or the work being done within the individual dispose functions?

public async dispose(): Promise<any> {

    return new Promise(async (err) => {
        await this.disposables.forEach(async disposable => {
            await disposable.dispose();
        });
        this.disposables.clear();
        let rmdir = promisify(fs.rmdir);
        let tempDir = this.getTempDir();
        try {
            await rmdir(tempDir);
        } catch (err) {
            try {
                this.outChannel.appendLine(`Error deleting ${tempDir}: ${err}.`);
            } catch (err2) { }
        }
    });
}

The content of disposables is created with this code:

        this.disposables.set(relativePath, {dispose: async () => {
            let unlink = promisify(fs.unlink);
            let rmdir = promisify(fs.rmdir);
            let readdir = promisify(fs.readdir);
            try {
                try {
                    this.outChannel.appendLine(`Cleaning up ${tempFullPath}...`);
                } catch(err2) { }
                await unlink(tempFullPath);
                relativePath = path.dirname(relativePath);
                while (/[^\\\.]+/.test(relativePath)) {
                    let parent = path.join(tempDir,relativePath);
                    if ((await readdir(parent)).length === 0) {
                        await rmdir(parent);
                    }
                    relativePath = path.dirname(relativePath);
                }
            } catch (err) {
                try {
                    this.outChannel.appendLine(`Failed - ${err}.`);
                } catch(err3) { }
            }
            return;
        }});

The result is that the final rmdir in the highest dispose is failing because the the directory isn't empty even though it is by the time I go look.

BlueMonkMN
  • 25,079
  • 9
  • 80
  • 146
  • 3
    Possible duplicate of [Using async/await with a forEach loop](https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop) – T.J. Crowder Mar 05 '19 at 16:59
  • A couple of other points: `async` functions **already** return promises, so `return new Promise` doesn't make any sense in an `async` function. Also, don't pass an `async` function into `new Promise` (unless you have all of the code in a `try`/`catch` block). The `Promise` constructor doesn't do anything with the promise the `async` function returns. – T.J. Crowder Mar 05 '19 at 17:01
  • @T.J.Crowder I added the "async" right before posting this code, not realizing what I was doing. Should I remove the "async" or the "new Promise"? – BlueMonkMN Mar 05 '19 at 17:06
  • The `new Promise`. The logic you currently have in the promise executor should just be top level logic in `dispose`. (And then apply the techniques from [the dupetarget](https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop) to handle the array of disposables.) – T.J. Crowder Mar 05 '19 at 17:10
  • ([Like this](https://pastebin.com/EPVhRVtg).) Since this (by SO's rules) a duplicate of the other question, please use the link (button?) in the banner at the top of your question that closes your question as a duplicate of it. Happy coding! – T.J. Crowder Mar 05 '19 at 17:24
  • Strange, there should be a "Yes, that answers my question" (or similar) button or link (separate from the link to the dupetarget). (Duplicates aren't necessarily a bad thing if we close them pointing at good answers; they can increase the search area, making it more likely someone else ends up getting led to those answers...) – T.J. Crowder Mar 05 '19 at 18:08
  • @T.J.Crowder is there a better place to continue this discussion? Like Meta? I don't see anything like that. Just "This question may already have an answer here: Using async/await with a forEach loop 12 answers" (and there's a link on the title of the other question to take me there). – BlueMonkMN Mar 05 '19 at 21:35
  • Weird! Well, don't worry about it. The question will get closed eventually. (Or you can delete it if you like, since it only marginally increases the search area.) Happy coding! :-) – T.J. Crowder Mar 06 '19 at 08:28

0 Answers0