Я разрабатываю расширение кода VS с использованием TypeScript, и мне нужно сделать несколько одновременных вызовов дочерних процессов для каждой папки в рабочей области с видимым всплывающим уведомлением о ходе выполнения. Завершение каждого нового дочернего процесса, скорее всего, займет несколько секунд.
Мой подход работает нормально с точки зрения вызовов child_process, но индикатор выполнения исчезает до завершения всех команд.
Вот пример кода, с которым я работал. Обратите внимание, что мое понимание использования функции async с Array.map заключается в том, что это приведет к одновременному запуску каждого await. Надеюсь, я прав с этим.
export async function doStuffCmdHandler(channel: vscode.OutputChannel, context: vscode.ExtensionContext): Promise<void> {
return vscode.window.withProgress({
title: "Doing Stuff...",
location: vscode.ProgressLocation.Notification,
}, async (progress) => {
if (vscode.workspace.workspaceFolders === undefined) {
throw Error("Command must be ran from within a VS Code Workspace");
} else {
channel.clear();
vscode.workspace.workspaceFolders.map(async (folder) => {
try {
// executeCommand() is a wrapper around child_process.exec which returns Promise<string>
let results = await executeCommand(folder.uri.path);
channel.show();
channel.append(results);
} catch (err) {
channel.show();
channel.append(`Error processing ${folder.uri.path}:\n\n`);
channel.append(`${(err as Error).message}\n\n`);
}
});
}
}
);
}
Если я делаю вызовы своего дочернего процесса последовательно с помощью обычного цикла for (согласно приведенному ниже фрагменту), у меня не возникает проблем с индикатором выполнения. Однако я бы предпочел делать эти вызовы одновременно:
channel.clear();
for (var folder of vscode.workspace.workspaceFolders) {
try {
// executeCommand() is a wrapper around child_process.exec which returns Promise<string>
let results = await executeCommand(folder.uri.path);
channel.show();
channel.append(results);
} catch (err) {
channel.show();
channel.append(`Error processing ${folder.uri.path}:\n\n`);
channel.append(`${(err as Error).message}\n\n`);
}
};



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


В вашем коде нигде не используется прогресс... Также вы не следите за выполнением обещаний, поэтому ваша функция заканчивается до окончания обещаний.
export async function doStuffCmdHandler(channel: vscode.OutputChannel, context: vscode.ExtensionContext): Promise<void> {
return vscode.window.withProgress({
title: "Doing Stuff...",
location: vscode.ProgressLocation.Notification,
}, async (progress) => {
if (vscode.workspace.workspaceFolders === undefined) {
throw Error("Command must be ran from within a VS Code Workspace");
} else {
channel.clear();
const total = vscode.workspace.workspaceFolders.length;
let done = 0;
// Return a promise that will end once all promises have finished.
return Promise.all(vscode.workspace.workspaceFolders.map(async (folder) => {
try {
// executeCommand() is a wrapper around child_process.exec which returns Promise<string>
let results = await executeCommand(folder.uri.path);
channel.show();
channel.append(results);
// Report something, reporting done vs total
progress.report(++done+"/"+total);
} catch (err) {
channel.show();
channel.append(`Error processing ${folder.uri.path}:\n\n`);
channel.append(`${(err as Error).message}\n\n`);
}
}));
}
}
);
}
Okok, я думал, вы хотите отобразить фактический прогресс :) В любом случае, это может оказаться удобным в какой-то момент.
Если мне не нужна безотказная природа Promise.all(), как это лучше всего реализовать с помощью Promise.allSettled()?
Да точно, так и должно быть
Спасибо @Salketer.
return Promise.all()...так очевидно, теперь я это вижу. Я играл сPromise.all()иPromise.allSettled()безрезультатно. Я полностью упустил из виду тот факт, что не возвращал его, а функция заканчивалась и отбрасывала окно уведомления. Я понимаю, что в моем примере кода не было использования объекта прогресса, это было целенаправленно. Если вы не сообщаете о каком-либо прогрессе, VS Code просто дает вам колеблющийся индикатор выполнения.