slug: checkcallback-logic-optimization
datetime: 2024-03-21 23:53
summary: checkCallback函数在按下快捷键和执行命令时被调用,返回结果影响命令是否显示,第一次传入true,第二次传入false。优化逻辑可以简化判断条件和提高复用性。
tags: checkCallback函数, 优化逻辑, 判断条件
cover_image_url: "https://images.unsplash.com/photo-1515378791036-0648a3ef77b2?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNjAwOTd8MHwxfHNlYXJjaHw4fHxjb21wdXRlcnxlbnwwfHx8fDE3MTEwMzY0NTV8MA&ixlib=rb-4.0.3&q=80&w=1080"
checkCallback判断逻辑优化
这里以 obsidian-sample-plugin 里的例子说明,官方代码如下:
this.addCommand({
id: 'open-sample-modal-complex',
name: 'Open sample modal (complex)',
checkCallback: (checking: boolean) => {
const markdownView = this.app.workspace.getActiveViewOfType(MarkdownView);
if (markdownView) {
if (!checking) {
new SampleModal(this.app).open();
}
return true;
}
return false;
}
});
这里的代码是什么意思呢?
通过测试得知,checkCallback 会被调用两次,第一次是按下 mod+p
时(这里的 mod 再 Windows 上是 ctrl,Mac 上是 command),第二次是选择命令时,比如这里当你执行 Open sample modal (complex)命令时。
在第一次时,如果 checkCallback 里返回 false,那么就不会把 Open sample modal (complex)命令加入到命令列表中,那么你也就无法执行命令了。但如果你返回 true,就会加入到命令列表,而不管你判断条件是什么。在第一次执行时,checking 的值总是 true。
第二次执行时,checking 的值,总是 false,这时无论你返回 true 还 false 都没有影响,只有第一次的返回有影响。
总结:
所以你的判断条件是什么,checkCallback api 根本就不关心,那是你自己代码逻辑应该关心的事。
有了上面的了解,可以把上面的代码逻辑做如下优化:
const markdownView = this.app.workspace.getActiveViewOfType(MarkdownView);
if(checking && !markdownView) return false;
if(checking && markdownView) return true;
if(!markdownView) return;
new SampleModal(this.app).open();
嗯,去掉逻辑嵌套,看起来舒服多了。
但是,还不够,每个地方都这样判断,也显得啰嗦,进一步优化:
//定义判断函数
const checkCondition = (checking: boolean, condition: any): boolean|string => {
//如果预检(第一次执行),且条件不符返回false
if(checking && !condition) return false;
//如果预检(第一次执行),且条件符合,返回true
if(checking && condition) return true;
//如果非预检(第二次执行),条件不符返回空
if(!condition) return '';
//如果非预检(第二次执行),且条件符合返回pass
return 'pass';
}
//实际使用
const markdownView = this.app.workspace.getActiveViewOfType(MarkdownView);
//判断条件是否符合,不符合返回
const checkRet = checkCondition(checking, markdownView)
if('pass' !== checkRet) return Boolean(checkRet);
//条件符合执行
new SampleModal(this.app).open();
这样逻辑看起来简单多了,而且方便复用。
结束。