【问题标题】:How Monaco Editor completion items provider can wait for async suggestions?Monaco Editor 完成项提供程序如何等待异步建议?
【发布时间】:2021-12-15 18:26:28
【问题描述】:

目标:等待来自虚假服务器响应的自定义建议。

问题:我无法理解如何告诉 Monaco 编辑器完成项提供者等待异步建议。

游乐场示例:

  1. Go to playground
  2. 粘贴以下代码
console.log("1. Instantiate a standalone code editor");

const language = "json"
const content = `{\n\t\"dependencies\": {\n\t\t\n\t}\n}\n`
const options = {
  value: content,
  language: language,
  tabSize: 2
}
const standaloneCodeEditor = monaco.editor.create(document.getElementById("container"), options);
const sce = standaloneCodeEditor;

console.log("2. Declare function to provide a completion items")

function provideCompletionItems(model, position) {
  console.log("Invoking function 'provideCompletionItems'")

  var textUntilPosition = model.getValueInRange({ startLineNumber: 1, startColumn: 1, endLineNumber: position.lineNumber, endColumn: position.column });
  console.log("textUntilPosition:", textUntilPosition)
    
  var match = textUntilPosition.match(/"dependencies"\s*:\s*\{\s*("[^"]*"\s*:\s*"[^"]*"\s*,\s*)*([^"]*)?$/);
  console.log("match:", match)

  if (!match) {
  return { suggestions: [] };
  }

  var word = model.getWordUntilPosition(position);
  console.log("word:", word)

  var range = {
    startLineNumber: position.lineNumber,
    endLineNumber: position.lineNumber,
    startColumn: word.startColumn,
    endColumn: word.endColumn
  };
  console.log("range:", range)

  const mock_serverResponse = [
    {
      label: '"lodash"',
      kind: monaco.languages.CompletionItemKind.Function,
      documentation: "The Lodash library exported as Node.js modules.",
      insertText: '"lodash": "*"',
      range: range
    },
    {
      label: '"lodash111"',
      kind: monaco.languages.CompletionItemKind.Function,
      documentation: "The Lodash111 library exported as Node.js modules.",
      insertText: '"lodash111": "*"',
      range: range
    },
    {
      label: '"express"',
      kind: monaco.languages.CompletionItemKind.Function,
      documentation: "Fast, unopinionated, minimalist web framework",
      insertText: '"express": "*"',
      range: range
    },
    {
      label: '"mkdirp"',
      kind: monaco.languages.CompletionItemKind.Function,
      documentation: "Recursively mkdir, like <code>mkdir -p</code>",
      insertText: '"mkdirp": "*"',
      range: range
    },
    {
      label: '"my-third-party-library"',
      kind: monaco.languages.CompletionItemKind.Function,
      documentation: "Describe your library here",
      insertText: '"${1:my-third-party-library}": "${2:1.2.3}"',
      insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
      range: range
    }
  ]

  let myCustomSuggestions = [];
  console.log("myCustomSuggestions:",myCustomSuggestions)

  setTimeout(() => {
    const myPromise = Promise.resolve(mock_serverResponse)
    console.log("myPromise:",myPromise)

    myPromise
      .then(response => {
        console.log("response:", response)
      
        response.forEach(e => myCustomSuggestions.push(e))
        console.log("myCustomSuggestions:",myCustomSuggestions)

        return {
          suggestions: myCustomSuggestions
        }
      })
      .catch(err => console.error(err)) 
  }, 2000)
  
}

console.log("3. Register completion items provider")
const completionItemProvider = monaco.languages.registerCompletionItemProvider(language, {
    provideCompletionItems: () => provideCompletionItems(sce.getModel(), sce.getPosition())
});

  1. 显示 Web 开发者控制台(查看日志消息)
  2. 运行程序
  3. 在括号中输入单词 lodash
  4. 查看网络开发者控制台
  5. 请注意,没有显示任何建议

【问题讨论】:

  • 为什么要等待建议?它会阻止你的用户界面。相反,使用承诺返回建议的方法是正确的方法。如果这需要更长的时间,摩纳哥将显示“正在加载...”弹出窗口。
  • 我想等待建议,因为在真正的应用程序中,不是这个简单的例子,建议是从服务器给出的......前端接受一个字符串并调用一个 API 端点 - 服务器返回一个建议列表用户可以使用它在编辑器中完成编辑。
  • 我想在 monaco 编辑器建议面板上看到“正在加载...” - 你能修改我的简单示例来告诉我如何获得它吗?
  • 在评论中很难做到。试试自己,更改provideCompletionItems 函数。删除现有的返回调用并改为返回:return new Promise((resolve, reject) =&gt; {}); 然后运行示例并使用 ctrl+空格触发代码完成。您将看到“正在加载...”弹出窗口,因为承诺永远不会被解决。

标签: javascript asynchronous promise monaco-editor


【解决方案1】:

这个问题很容易解决。

首先,在需要竞争的时候不要展示任何东西,或者展示你喜欢的东西。并且你需要知道如何主动展示建议。是的,使用此代码:

isReady=true;
yourEditor.trigger('anything', 'editor.action.triggerSuggest', {});

现在我们可以随时显示建议。

现在我们明白了!

let yourSuggestions = [];
monaco.languages.registerCompletionItemProvider('vb', {
    provideCompletionItems: function (model, position) {
        // show some waitting message here
        if(isReady){
            return {suggestion: yourSuggestions}
        }
        requestSuggestions();
        return {suggestions:[]};
    }
});

function requestSuggestions(){
    // do something you need
    $.ajax({
        //.....
        success(data){
            isReady = true;
            yourSuggestions = data.suggestions;
            yourEditor.trigger('anything', 'editor.action.triggerSuggest', {});
        }
    })
}

这只是一种方法,你可以证明它

【讨论】:

    猜你喜欢
    • 2014-04-03
    • 2020-10-04
    • 2022-10-14
    • 2019-05-31
    • 1970-01-01
    • 2020-02-22
    • 2013-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多