【问题标题】:Async/await again: Where to put await and return?再次异步/等待:在哪里放置等待和返回?
【发布时间】:2021-08-12 14:52:46
【问题描述】:

在 VSCode 扩展中,我有一个函数可以从当前工作区中删除某些目录。但该函数不会等待目录被删除。

The accepted answer for this Stackoverflow question 是有道理的,但我仍然无法弄清楚如何使我的功能正常工作。我在哪里等待并返回?

async function cleanUpWorkspace(workspace: any) {
    const fs = require('fs');
    const rimraf = require("rimraf");
    var targetFolders = ['dirA', 'dirB', 'dirC', 'dirD'];

    try {
        await targetFolders.forEach(function (value) { //'await' has no effect on the type of this expression.
            let targetPath = workspace + "\\\\" + value;
            if (fs.existsSync(targetPath)) {
                fs.promises.access(targetPath);
                rimraf(targetPath, function (err: any) {
                    if (err) {
                        console.log(err);
                    } else {
                        console.log("Directory: " + value + " was deleted");
                    }
                });
            } else {
                console.log(value + " doesn't exist.");
            }
        });
        return Promise.resolve();
    } catch (error) {
        console.log(error);
    }
}

async function prepare() {
    await cleanUpWorkspace(workspace);
}
  • 打字稿 4.3.5
  • node.js 14.17.0

【问题讨论】:

  • forEach 不返回承诺,所以await 它没用。

标签: node.js typescript vscode-extensions


【解决方案1】:
  • 您只能在 async function 或异步箭头函数 (async () => { /* function contents */ }) 中使用 await
  • 您应该只在返回 Promise 的函数上使用 await
  • 所有async函数,不管它们是否return一个值,都返回一个Promise。如果内部没有返回值,则返回类型为Promise<void>(类似于常规函数在没有返回值时隐式返回void

您正在尝试在传递给forEach 的函数内执行异步操作(即调用返回承诺的函数)。理想情况下,我们会await他们。要使用await,我们需要将传递给forEach 的函数设为async 函数。但是,forEach 内部没有 await 承诺。这意味着您的 forEach 函数中未捕获的异常无法弥补 try/catch 块。

为避免这种情况,我们可以使用for..of 循环。

因为async 函数会自动返回Promise,所以没有真正需要return Promise.resolve() 的理由

  try {
      for (const value of targetFolders) {
        let targetPath = workspace + "\\\\" + value;
        if (fs.existsSync(targetPath)) {
            await fs.promises.access(targetPath);
            rimraf(targetPath, function (err: any) {
                if (err) {
                    console.log(err);
                } else {
                    console.log("Directory: " + value + " was deleted");
                }
            });
        } else {
            console.log(value + " doesn't exist.");
        }
      }
  } catch (error) {
      console.log(error);
  }

现在,我们可以await 拨打fs.promises.access 了。


我们可以做的另一件事是承诺rimraf。 Node 标准库中有一个函数——util.promisify——将接受回调的函数转换为返回承诺的函数。所以,如果我们有

const util = require("util")
const rimrafPromise = util.promisify(rimraf)

那么我们就可以了

  try {
      for (const value of targetFolders) {
        let targetPath = workspace + "\\\\" + value;
        if (fs.existsSync(targetPath)) {
            await fs.promises.access(targetPath);
            await rimrafPromise(targetPath);
            console.log("Directory: " + value + " was deleted");
        } else {
            console.log(value + " doesn't exist.");
        }
      }
  } catch (error) {
      console.log(error);
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-13
    • 1970-01-01
    • 2013-03-22
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    • 2014-12-30
    相关资源
    最近更新 更多