You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VS Code CodeLens异步调用阻塞编辑器 如何基于resolveCodeLens优化

实现方案

核心逻辑

因为你在API返回前无法获知range信息,所以不能完全套用官方“先返回range后填充command”的默认流程,需要搭配主动刷新机制实现,完全避免阻塞主线程:

  1. provideCodeLenses 仅做快速返回和请求触发,不等待异步网络调用完成
  2. 后台异步拉取API数据,拿到range和元数据后存入缓存,主动触发CodeLens刷新
  3. 所有command的构造逻辑全部放到resolveCodeLens中实现,仅当用户可视区域出现对应CodeLens时才执行填充

具体实现步骤

  • 第一步:调整provideCodeLenses逻辑

    首先给Provider类加两个缓存字段:
    // 存储已拉取到的文档对应CodeLens range和元数据
    private lensMetaCache = new Map<string, Array<{range: vscode.Range, meta: any}>>();
    // 标记正在请求中的文档,避免重复发起调用
    private requestingDocs = new Set<string>();
    
    改造后的provideCodeLenses代码:
    public provideCodeLenses(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.CodeLens[] | Thenable<vscode.CodeLens[]> {        
      if (!vscode.workspace.getConfiguration().get('stenography.codeLensMode')) {
        return [];
      }
      const filename = document.uri.toString();
      // 已有缓存直接返回仅带range的CodeLens,不带command
      if (this.lensMetaCache.has(filename)) {
        return this.lensMetaCache.get(filename)!.map(item => new vscode.CodeLens(item.range));
      }
      // 没有缓存且没有正在请求,后台触发请求,直接返回空数组
      if (!this.requestingDocs.has(filename)) {
        this.requestingDocs.add(filename);
        // 异步请求不阻塞返回
        vscode.window.withProgress({
          location: vscode.ProgressLocation.Window,
          cancellable: false,
          title: 'Fetching from Stenography Autopilot'
        }, async (progress) => {
          try {
            progress.report({ increment: 0 });
            const language = document.languageId;
            const data = await fetchStenographyAutopilot(STENOGRAPHY_API_KEY!, document.getText(), language, false);
            const lensMetas = [];
            data.code_blocks.forEach((block: any) => {
              const firstLine = document.lineAt(block.startPosition.row - 1);
              const textRange = new vscode.Range(firstLine.range.start, firstLine.range.end);
              lensMetas.push({
                range: textRange,
                meta: block.stenographyResult
              });
            });
            // 存入缓存
            this.lensMetaCache.set(filename, lensMetas);
            // 主动触发CodeLens刷新
            vscode.languages.refreshCodeLenses();
          } catch (e) {
            console.error(e);
          } finally {
            this.requestingDocs.delete(filename);
          }
        });
      }
      // 直接返回空,不阻塞
      return [];
    }
    
  • 第二步:实现resolveCodeLens方法

    public resolveCodeLens(codeLens: vscode.CodeLens, token: vscode.CancellationToken): vscode.ProviderResult<vscode.CodeLens> {
      // 遍历缓存找到对应range的元数据,构造command
      for (const metas of this.lensMetaCache.values()) {
        const matched = metas.find(item => item.range.isEqual(codeLens.range));
        if (matched) {
          codeLens.command = {
            title: "<stenography autopilot />",
            tooltip: matched.meta.pm,
            command: "stenography.codelensAction",
            arguments: [matched.meta.pm]
          };
          return codeLens;
        }
      }
      return codeLens;
    }
    
  • 第三步:补充缓存清理逻辑

    监听文档变更、关闭事件,对应删除缓存,避免展示旧数据:
    // 可以在Provider初始化时注册监听
    vscode.workspace.onDidChangeTextDocument(e => {
      this.lensMetaCache.delete(e.document.uri.toString());
    });
    vscode.workspace.onDidCloseTextDocument(doc => {
      this.lensMetaCache.delete(doc.uri.toString());
    });
    

为什么不会阻塞

provideCodeLenses 收到调用后会立刻返回结果,所有网络请求、数据处理逻辑全部在后台异步执行,不会占用VS Code主线程时间。主动刷新机制保证API返回后CodeLens能正常展示,resolveCodeLens的懒加载逻辑也完全符合官方的性能优化建议。

内容的提问来源于stack exchange,提问作者Bram Adams

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 23:06:02