ori*_*and 5 typescript visual-studio-code vscode-extensions
我对标题感到非常抱歉,我不知道如何更好地描述我的问题。
我想实现 VSCode 的 withProgress API,以便能够在我的代码运行/进行时显示进度条。文档在这里:https : //code.visualstudio.com/api/extension-capabilities/common-capabilities#progress-api
我试图实现它:
vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: "I am long running!",
}, (progress, token) => {
return new Promise(resolve => {
const output = executeProcess('sleep 5');
resolve();
});
});
Run Code Online (Sandbox Code Playgroud)
executeProcess(...) 是 npm child_process.spawnSync 的包装器。我需要它是同步的,因为我想阅读它的标准输出。
所以,我的问题是它当前正在运行 executeProcess,当它完成时,它开始显示进度条。我怎么能写成它首先开始显示进度条的方式,同时它正在运行并在后台完成它的工作?
是否有可能不需要重构我的代码来使用 child_process.spawn 和回调?
Jan*_*jsi 10
是的,我认为您必须更改代码以使用异步模式,否则您将阻塞要同时呈现进度对话框的 UI 线程。
这是使用spawn和之间的区别spawnSync:
如何在异步方法中读取子进程输出的示例如下:
let childProcess = spawn(someProcessToSpawn)
.on("close", (code, signal) => {
console.log(`Closed: ${code} ${signal}`);
if (childProcess.killed) { console.log('KILLED'); }
resolve();
clearInterval(interval);
})
.on("error", err => {
reject(err);
});
childProcess.stdout
.on("data", (chunk: string | Buffer) => {
// YOUR CODE GOES HERE
console.log(`stdout: ${chunk}`);
progressUpdate = chunk.toString('utf8', 0, 50).replace(/[\r\n]/g, '');
});
Run Code Online (Sandbox Code Playgroud)
如果要运行整个示例,请克隆progress-sample,运行npm install并使用以下代码替换extension.ts内容:
'use strict';
import { ExtensionContext, window, commands, ProgressLocation, CancellationToken, Progress } from 'vscode';
import { spawn, spawnSync } from 'child_process';
export function activate(context: ExtensionContext) {
context.subscriptions.push(commands.registerCommand('extension.startTask', async () => {
let mode = await window.showQuickPick(['sync', 'async'], { placeHolder: 'Pick mode...' });
window.withProgress({
location: ProgressLocation.Notification,
title: "I am long running",
cancellable: true
}, async (progress, token) => {
token.onCancellationRequested(() => {
console.log("User canceled the long running operation");
});
switch (mode) {
case undefined:
return; // canceled by the user
case 'sync':
return spawnSomethingSync(token);
case 'async':
default:
return spawnSomethingAsync(progress, token);
}
});
}));
}
/**
* Synchronous approach
* @param _token cancellation token (unused in the sync approach)
*/
function spawnSomethingSync(_token: CancellationToken): Promise<void> {
return new Promise(resolve => {
console.log('Started...');
let child = spawnSync('cmd', ['/c', 'dir', '/S'], { cwd: 'c:\\', encoding: 'utf8' });
console.log(`stdout: ${child.stdout.slice(0, 1000)}`); // otherwise it is too big for the console
resolve();
});
}
/**
* Asynchronous approach
* @param token cancellation token (triggered by the cancel button on the UI)
*/
function spawnSomethingAsync(progress: Progress<{ message?: string; increment?: number }>, token: CancellationToken): Promise<void> {
return new Promise<void>((resolve, reject) => {
if (token.isCancellationRequested) {
return;
}
var progressUpdate = 'Starting up...';
const interval = setInterval(() => progress.report({ message: progressUpdate }), 500);
let childProcess = spawn('cmd', ['/c', 'dir', '/S'], { cwd: 'c:\\' })
.on("close", (code, signal) => {
console.log(`Closed: ${code} ${signal}`);
if (childProcess.killed) { console.log('KILLED'); }
resolve();
clearInterval(interval);
})
.on("error", err => {
reject(err);
});
childProcess.stdout
.on("data", (chunk: string | Buffer) => {
// YOUR CODE GOES HERE
console.log(`stdout: ${chunk}`);
progressUpdate = chunk.toString('utf8', 0, 50).replace(/[\r\n]/g, '');
});
token.onCancellationRequested(_ => childProcess.kill());
});
}
Run Code Online (Sandbox Code Playgroud)
如果您不在 Windows 上,只需将dir /S和替换为c:\\其他一些适当的长时间运行的命令。
使用异步方法的另一个好处是可以轻松连接取消按钮以终止生成的进程:
token.onCancellationRequested(_ => childProcess.kill());
Run Code Online (Sandbox Code Playgroud)
...您还有机会通过更新progress对象来显示进度。
| 归档时间: |
|
| 查看次数: |
1667 次 |
| 最近记录: |