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

VS Code扩展如何判断TypeScript语言服务已就绪可查询?

如何等待VS Code中TypeScript语言服务就绪后发起请求?

我正在开发一款名为Any Xray的VS Code扩展,它会向内置TypeScript语言服务发送quickinfo请求,目标是查找类型为any的符号。目前使用的查询代码如下:

/** Leverages the `tsserver` protocol to try to get the type info at the given `position`. */
export async function quickInfoRequest(model: vscode.TextDocument, position: vscode.Position) {
  const { scheme, fsPath, authority, path } = model.uri;
  return await vscode.commands.executeCommand<QuickInfoResponse | undefined>(
    "typescript.tsserverRequest",
    "quickinfo",
    {
      file: scheme === 'file' ? fsPath : `^/${scheme}/${authority || 'ts-nul-authority'}/${path.replace(/^\//, '')}`,
      line: position.line + 1,
      offset: position.character,
    } satisfies FileLocationRequestArgs
  );
}

该方案运行良好,但前提是需在语言服务完全加载并“稳定”后再发起查询。如果过早发起涉及导入的查询,语言服务会返回any类型,导致大量误报警告。我希望等待TypeScript服务准备就绪后再发起请求,请问是否有办法检查服务是否仍在加载中?或者是否有可监听的事件来获知服务已就绪可查询?


解决方案

1. 监听typescript.tsServerStarted事件

VS Code的TypeScript扩展会在服务启动完成后触发typescript.tsServerStarted命令事件,你可以通过监听这个事件来标记服务就绪状态:

let tsServerReady = false;

// 在扩展激活逻辑中注册监听
export function activate(context: vscode.ExtensionContext) {
  // 监听TS服务启动完成事件
  const serverStartedDisposable = vscode.commands.registerCommand('typescript.tsServerStarted', () => {
    tsServerReady = true;
    serverStartedDisposable.dispose(); // 只需要监听一次启动
  });
  context.subscriptions.push(serverStartedDisposable);

  // 配置变更时重置就绪状态(可选)
  const configChangeDisposable = vscode.workspace.onDidChangeConfiguration(e => {
    if (e.affectsConfiguration('typescript')) {
      tsServerReady = false;
      // 重新监听服务启动
      const newDisposable = vscode.commands.registerCommand('typescript.tsServerStarted', () => {
        tsServerReady = true;
        newDisposable.dispose();
      });
      context.subscriptions.push(newDisposable);
    }
  });
  context.subscriptions.push(configChangeDisposable);
}

// 封装安全的查询函数
async function safeQuickInfoRequest(model: vscode.TextDocument, position: vscode.Position) {
  // 等待服务就绪
  if (!tsServerReady) {
    await new Promise(resolve => {
      const disposable = vscode.commands.registerCommand('typescript.tsServerStarted', () => {
        tsServerReady = true;
        disposable.dispose();
        resolve(null);
      });
    });
  }
  return quickInfoRequest(model, position);
}

2. 通过projectInfo请求检查服务状态

你可以向TS服务发送projectInfo请求,根据返回结果判断服务是否能正常处理请求:

async function isTsServerReady(document: vscode.TextDocument): Promise<boolean> {
  try {
    const response = await vscode.commands.executeCommand(
      "typescript.tsserverRequest",
      "projectInfo",
      {
        file: document.uri.fsPath,
        needFileNameList: false
      }
    );
    // 无错误且返回有效数据则认为就绪
    return !!response && typeof response === 'object' && !response.error;
  } catch (error) {
    return false;
  }
}

// 带重试的安全查询
async function safeQuickInfoRequest(model: vscode.TextDocument, position: vscode.Position) {
  // 循环检查直到服务就绪,添加延迟避免频繁请求
  while (!await isTsServerReady(model)) {
    await new Promise(resolve => setTimeout(resolve, 150));
  }
  return quickInfoRequest(model, position);
}

3. 结合文本编辑器状态监听

如果你的查询是在文件打开时触发,可以结合onDidOpenTextDocument事件,等待文档关联的TS服务完成初始化:

context.subscriptions.push(
  vscode.workspace.onDidOpenTextDocument(async doc => {
    if (doc.languageId === 'typescript' || doc.languageId === 'typescriptreact') {
      // 等待服务就绪
      await safeQuickInfoRequest(doc, new vscode.Position(0, 0));
      // 执行后续逻辑
    }
  })
);

注意事项

  • 大型项目中TS服务加载依赖的时间较长,建议结合延迟重试机制,避免一次性判断失败就终止流程
  • 若扩展需要处理动态配置变更,记得在配置更新后重置服务就绪状态,确保后续查询的准确性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 09:58:18