Monaco Editor:provideInlineCompletions请求报错致代码渲染异常求助
在实现Monaco Editor的provideInlineCompletions方法时,发送异步请求获取补全内容时出现以下报错:
async.js:37 Uncaught (in promise) Canceled: Canceled
at Listener.invoke
at PrivateEventDeliveryQueue.deliver
at Emitter.fire at MutableToken.cancel
at CancellationTokenSource.cancel
at Object.cancel
at UpdateOperation.dispose
at MutableDisposable.dispose
at dispose
这个问题的核心是:Monaco会在触发新的补全请求(比如用户连续输入、光标移动)时,自动取消之前未完成的请求。如果未捕获这个取消操作抛出的Canceled异常,会导致Promise链中断,最终补全内容无法正常渲染。
以下是具体解决方案:
捕获取消异常并返回合法结构
在异步逻辑中直接捕获Canceled异常,确保无论请求成功还是被取消,都返回符合Monaco要求的补全结构,避免未处理的Promise错误中断流程。示例代码:async function provideInlineCompletions(model, position, context, token) { try { // 发送异步请求获取补全数据 const completions = await fetch('/api/get-completions', { method: 'POST', body: JSON.stringify({ content: model.getValue(), line: position.lineNumber, column: position.column }) }).then(res => res.json()); return { items: completions }; } catch (error) { // 识别并处理取消异常 if (error.message === 'Canceled') { // 请求被取消时返回空补全列表,避免编辑器报错 return { items: [] }; } // 处理其他请求错误 console.error('补全请求失败:', error); return { items: [] }; } }绑定Monaco取消令牌与请求取消逻辑
如果使用支持请求取消的库(如axios),可以将Monaco的取消令牌和请求的取消机制绑定,提前终止无效请求,减少资源浪费:const CancelToken = axios.CancelToken; let cancelRequest; async function provideInlineCompletions(model, position, context, token) { try { // 绑定Monaco取消事件到请求取消 token.onCancellationRequested(() => { if (cancelRequest) cancelRequest('Monaco已取消补全请求'); }); const response = await axios.post('/api/get-completions', { content: model.getValue(), line: position.lineNumber, column: position.column }, { cancelToken: new CancelToken(c => cancelRequest = c) }); return { items: response.data }; } catch (error) { // 判断是否是请求取消错误 if (axios.isCancel(error)) { return { items: [] }; } console.error('补全请求失败:', error); return { items: [] }; } finally { cancelRequest = null; } }避免返回undefined或非法结构
无论请求结果如何,必须返回包含items数组的InlineCompletions对象,哪怕是空数组。返回undefined或不符合要求的结构会直接导致编辑器渲染异常。
内容的提问来源于stack exchange,提问作者yuan TANG

