我必须在Visual Studio代码扩展中实现一个非常典型的编程模式:将某些内容保存到文件中,但在执行此操作之前检查目标文件是否存在,并询问用户是否可以覆盖它,如果是的话
通常我只会打开一个文件保存对话框,要求用户给我一个文件名,这个对话框会进行所有必要的检查,并在必要时获得用户确认。但是在vscode中我们没有文件保存对话框(但是它有a feature request)。因此,我试图用我们在那里的有限手段来实现这一点。幸运的是,几周前,一个新的选项参数被添加到消息对话框中,以允许它们模态化。但不知何故,我无法获得正确的时机。这是我的代码:
window.showInputBox({
placeHolder: "<Enter full file name here>",
prompt: "Enter the name to an html file to save the diagram\n" }
).then((value: string) => {
if (value) {
let canWrite = true;
if (fs.existsSync(value)) {
canWrite = false;
window.showWarningMessage("The specified file exists already", { modal: true }, ...[ "Overwrite" ]).then((action: string) => {
if (action === "Overwrite") {
canWrite = true;
}
});
}
if (canWrite) {
var stream = fs.createWriteStream(value, { encoding: "utf-8", autoClose: true });
stream.on("error", function (error: any) {
window.showErrorMessage("Could not write to file '" + value + "'. " + error);
});
stream.once('open', function (fd) {
stream.write(text);
stream.end();
window.showInformationMessage("Diagram successfully written to file '" + value + "'.");
});
}
}
})
问题是对window.showWarningMessage
的调用是非阻塞的,这意味着当对话框(它本身是模态的)在if (canWrite)
已经执行之后打开代码。这不是一个大问题,因为canWrite
此时false
是showWarningMessage
,但是,一旦showInputBox
然后返回,则外部可执行的任何代码不再执行(来自if (canWrite)
) ,即"code" so I can post this
不再执行(正如我所料)。是否无法嵌套2个人或者我还有什么其他错误?
有经验的打字稿/ vscode develper如何处理这项任务?
答案 0 :(得分:1)
showWarningMessage
根据需要不可用,你无法嵌套它。相反,您必须创建自己的Thenable方法,这需要一些重构。
主要想法是保存必须返回Promise
,并且会控制showWarningMessage
返回(需要时)
function saveDiagram(text, filename): Promise<string | boolean> {
return new Promise((resolve, reject) => {
if (fs.existsSync(filename)) {
vscode.window.showWarningMessage("The specified file exists already", { modal: true }, ...[ "Overwrite" ]).then((action: string) => {
if (action === "Overwrite") {
resolve(filename);
} else {
resolve(false);
}
});
} else {
resolve(filename);
}
});
}
还将在磁盘上编写图表作为新函数提取,称为后者:
function writeDiagramOnDisk(text, filename) {
var stream = fs.createWriteStream(filename, { encoding: "utf-8", autoClose: true });
stream.on("error", function (error: any) {
vscode.window.showErrorMessage("Could not write to file '" + filename + "'. " + error);
});
stream.once('open', function (fd) {
stream.write(text);
stream.end();
vscode.window.showInformationMessage("Diagram successfully written to file '" + filename + "'.");
});
}
现在,您的扩展代码将采用可靠的方法,正如您所期望的那样:
vscode.window.showInputBox({
placeHolder: "<Enter full file name here>",
prompt: "Enter the name to an html file to save the diagram\n" }
).then((value: string) => {
if (value) {
saveDiagram(text, value)
.then((filename) => {
if (filename) {
writeDiagramOnDisk(text, filename)
}
});
}
})