简体   繁体   English

如何显示 Promise 并发的进度通知

[英]How can I show Progress Notification with Promise Concurrency

I am developing a VS Code Extension using TypeScript and need to make some concurrent child-process calls for each folder in the workspace, with a visible progress notification popup.我正在使用 TypeScript 开发一个 VS 代码扩展,需要为工作区中的每个文件夹进行一些并发子进程调用,并显示一个可见的进度通知弹出窗口。 Each new child process will likely take a few seconds to complete.每个新的子进程可能需要几秒钟才能完成。

My approach seems to work fine from the perspective of the child_process calls but the progress bar disappears before all the commands have completed.从 child_process 调用的角度来看,我的方法似乎工作正常,但进度条在所有命令完成之前消失。

Here is a sample of the code I have been working with.这是我一直在使用的代码示例。 Note that my understanding of using an async function with Array.map is that it will result in each await being ran concurrently.请注意,我对将async function 与Array.map一起使用的理解是,它将导致每个await同时运行。 Hopefully I am correct with that.希望我是正确的。

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`);
                    }
                });
            }
        }
    );
}

If I make my child process calls sequentially with a regular for loop (as per the snippet below) then I don't have any progress bar issues.如果我使用常规 for 循环按顺序调用我的子进程(按照下面的代码片段),那么我没有任何进度条问题。 Howevever, I would prefer to make these calls concurrently:但是,我更愿意同时进行这些调用:

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`);
    }
};

There is no use of progress anywhere in your code... Also you are not following the execution of the promises so your function ends before the promises end.您的代码中的任何地方都没有使用进度...您也没有遵循承诺的执行,因此您的 function 在承诺结束之前结束。

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`);
                    }
                }));
            }
        }
    );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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