Async/await 再次:等待和 return 放在哪里?
Async/await again: Where to put await and return?
在 VSCode 扩展中,我有一个函数可以从当前工作区中删除某些目录。但是该函数不会等待目录被删除。
The accepted answer for this Whosebug question 有道理,但我仍然不知道如何使我的函数正常工作。我在哪里放置 await 和 return?
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
- 您只能在
async function
或异步箭头函数 (async () => { /* function contents */ }
) 中使用 await
- 您应该只在 return 一个 Promise
的函数上使用 await
- 所有
async
函数,无论它们是否return
一个值,return一个Promise
。如果里面没有 return 值,则 return 类型是 Promise<void>
(类似于常规函数隐式 return void
如果它们没有一个 return 值)
您正在尝试在传递给 forEach
的函数内部执行异步操作(即调用 return 承诺的函数)。理想情况下,我们会 await
他们。要使用 await
,我们需要将传递给 forEach
的函数设为 async
函数。然而,forEach
并没有在内部 await
承诺。这意味着 forEach
函数中未捕获的异常不会弥补 try
/catch
块。
为了避免这种情况,我们可以使用 for..of
循环。
因为 async
自动运行 return 和 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
调用。
我们可以做的另一件事是 promisify rimraf
。 Node 标准库中有一个函数 -- util.promisify
-- 将接受回调的函数转换为函数 returning promises。所以,如果我们有
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);
}
在 VSCode 扩展中,我有一个函数可以从当前工作区中删除某些目录。但是该函数不会等待目录被删除。
The accepted answer for this Whosebug question 有道理,但我仍然不知道如何使我的函数正常工作。我在哪里放置 await 和 return?
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
- 您只能在
async function
或异步箭头函数 (async () => { /* function contents */ }
) 中使用await
- 您应该只在 return 一个 Promise 的函数上使用
- 所有
async
函数,无论它们是否return
一个值,return一个Promise
。如果里面没有 return 值,则 return 类型是Promise<void>
(类似于常规函数隐式 returnvoid
如果它们没有一个 return 值)
await
您正在尝试在传递给 forEach
的函数内部执行异步操作(即调用 return 承诺的函数)。理想情况下,我们会 await
他们。要使用 await
,我们需要将传递给 forEach
的函数设为 async
函数。然而,forEach
并没有在内部 await
承诺。这意味着 forEach
函数中未捕获的异常不会弥补 try
/catch
块。
为了避免这种情况,我们可以使用 for..of
循环。
因为 async
自动运行 return 和 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
调用。
我们可以做的另一件事是 promisify rimraf
。 Node 标准库中有一个函数 -- util.promisify
-- 将接受回调的函数转换为函数 returning promises。所以,如果我们有
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);
}