确定 JavaScript 语法在 ACE 的更改处理程序中是否有效

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9506154/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 06:54:41  来源:igfitidea点击:

Determine if JavaScript syntax is valid in change handler of ACE

javascriptace-editor

提问by Phrogz

I'm using the ACEeditor for interactive JavaScript editing. When I set the editor to JavaScript mode, ACE automatically determines if the code is valid or not, with an error message and line number highlighted when it's not.

我正在使用ACE编辑器进行交互式 JavaScript 编辑。当我将编辑器设置为 JavaScript 模式时,ACE 会自动确定代码是否有效,如果无效,则会突出显示错误消息和行号。

During the changeevent handler, I want to detect if ACE thinks the code is valid or not before I attempt to eval()it. The only way I thought that I might do it is:

change事件处理程序期间,我想在我尝试之前检测 ACE 是否认为代码有效eval()。我认为我可能会这样做的唯一方法是:

var jsMode = require("ace/mode/javascript").Mode;
var editor = ace.edit('mycode'), edEl = document.querySelector('#mycode');
editor.getSession().setMode(new jsMode);
editor.getSession().on('change',function(){
  // bail out if ACE thinks there's an error
  if (edEl.querySelector('div.ace_gutter-cell.ace_error')) return;
  try{
    eval(editor.getSession().getValue());
  }catch(e){}
});

However:

然而:

  1. Leaning on the presence of an element in the UI with a particular class seems awfully fragile, but more importantly,
  2. The visual update for parsing occurs afterthe changecallback occurs.
  1. 依靠特定类的 UI 元素的存在似乎非常脆弱,但更重要的是,
  2. 发生解析视觉更新change回调发生。

Thus, I actually have to wait more than 500ms (the delay before the JavaScript worker kicks in):

因此,我实际上必须等待超过 500 毫秒(JavaScript 工作程序启动之前的延迟):

editor.getSession().on('change',function(){
  setTimeout(function(){
    // bail out if ACE thinks there's an error
    if (edEl.querySelector('div.ace_gutter-cell.ace_error')) return;
    try{
      eval(editor.getSession().getValue());
    }catch(e){}
  },550); // Must be longer than timeout delay in javascript_worker.js
});

Is there a better way, something in an undocumented API for the JS mode, to ask whether there are any errors or not?

有没有更好的方法,在未记录的 JS 模式 API 中,询问是否有任何错误?

回答by hkrish

The current session fires onChangeAnnotationevent when annotations change.

当注释更改时,当前会话会触发onChangeAnnotation事件。

after that the new set ofannotations can be retrieved as follows

之后,可以按如下方式检索新的注释

var annotations = editor.getSession().getAnnotations();

seems to do the trick. It returns a JSON object which has the rowas keyand an array as value. The valuearray may have more than one object, depending on whether there are more than one annotation for each row.

似乎可以解决问题。它返回其具有JSON对象作为关键和阵列作为。该阵列可以具有多于一个的对象,这取决于是否存在用于每行多于一个注释。

the structure is as follows (copied from firebug –for a test script that I wrote)

结构如下(复制自firebug——我写的一个测试脚本)

// annotations would look like
({

82:[
    {/*annotation*/
        row:82, 
        column:22, 
        text:"Use the array literal notation [].", 
        type:"warning", 
        lint:{/*raw output from jslint*/}
    }
],

rownumber : [ {anotation1}, {annotation2} ],

...

});

so..

所以..

editor.getSession().on("changeAnnotation", function(){

    var annot = editor.getSession().getAnnotations();

    for (var key in annot){
        if (annot.hasOwnProperty(key))
            console.log("[" + annot[key][0].row + " , " + annot[key][0].column + "] - \t" + annot[key][0].text);
    }

});

// thanks http://stackoverflow.com/a/684692/1405348 for annot.hasOwnProperty(key) :)

should give you a list of all annotations in the current Ace edit session, when the annotations change!

当注释更改时,应该会为您提供当前 Ace 编辑会话中所有注释的列表!

Hope this helps!

希望这可以帮助!

回答by AndrewKS

I found a solution that is probably faster than traversing the DOM. The editor's session has a getAnnotations method you can use. Each annotation has a type that shows whether they are an error or not.

我找到了一个可能比遍历 DOM 更快的解决方案。编辑器的会话有一个您可以使用的 getAnnotations 方法。每个注释都有一个类型,用于显示它们是否是错误。

Here is how I set my callback for the on 'change'

这是我为“更改”设置回调的方法

function callback() {
    var annotation_lists = window.aceEditor.getSession().getAnnotations();
    var has_error = false;

    // Unfortunately, you get back a list of lists. However, the first list is
    //   always length one (but not always index 0)
    go_through:
    for (var l in annotation_lists) {
        for (var a in annotation_lists[l]) {
            var annotation = annotation_lists[l][a];
            console.log(annotation.type);
            if (annotation.type === "error") {
                has_error = true;
                break go_through;
            }
        }
    }

    if (!has_error) {
        try {
            eval(yourCodeFromTextBox);
            prevCode = yourCodeFromTextBox;
        }
        catch (error) {
            eval(prevCode);
        }
    }
}

As far as I know, there are two other types for annotations: "warning" and "info", just in case you'd like to check for those as well.

据我所知,注释还有另外两种类型:“警告”和“信息”,以防万一您也想检查它们。

I kept track of the pervious code that worked in a global (well, outside the scope of the callback function) because often there would be errors in the code but not in the list of annotations. In that case, when eval'ing the errored code, it would be code and eval the older code instead.

我跟踪了以前在全局中工作的代码(好吧,在回调函数的范围之外),因为代码中通常会出现错误,但注释列表中不会。在这种情况下,当评估错误的代码时,它将改为 code 并评估旧代码。

Although it seems like two evals would be slower, it seems to me like the performance is no that bad, thus far.

虽然看起来两个 eval 会更慢,但在我看来,到目前为止,性能并没有那么糟糕。

回答by Jan Jongboom

Ace uses JsHintinternally (in a worker) and as you can see in the file there is an event emitted:

AceJsHint在内部使用(在worker 中),正如您在文件中看到的,发出了一个事件:

this.sender.emit("jslint", lint.errors);

You can subscribeto this event, or call the JSHint code yourself (it's pretty short) when needed.

你可以订阅这个事件,或者在需要时自己调用 JSHint 代码(它很短)。

回答by mios

I found you can subscribe worker events in Ace 1.1.7:

我发现你可以在 Ace 1.1.7 中订阅工人事件:

For javascript code, subscribe 'jslint' event:

对于 javascript 代码,订阅 'jslint' 事件:

session.setMode('ace/mode/javascript}');
session.on('changeMode', function() {
  if (session.$worker) {
    session.$worker.on('jslint', function(lint) {
      var messages = lint.data, types;
      if (!messages.length) return ok();
      types = messages.map(function(item) {
        return item.type;
      });
      types.indexOf('error') !== -1 ? ko() : ok();
    });
  }
});

For JSON code, subscribe 'error' and 'ok' event:

对于 JSON 代码,订阅 'error' 和 'ok' 事件:

session.setMode('ace/mode/json');
session.on('changeMode', function() {

  // session.$worker is available when 'changeMode' event triggered
  // You could subscribe worker events here, whatever changes to the
  // content will trigger 'error' or 'ok' events.

  session.$worker.on('error', ko);
  session.$worker.on('ok', ok);
});