24

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

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){}
});

然而:

  1. 依靠 UI 中具有特定类的元素的存在似乎非常脆弱,但更重要的是,
  2. 解析的视觉更新发生change回调发生之后。

因此,我实际上必须等待超过 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
});

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

4

4 回答 4

28

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

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

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

似乎可以解决问题。它返回一个 JSON 对象,其中作为,数组作为数组可能有多个对象,具体取决于每一行是否有多个注解。

结构如下(从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} ],

...

});

所以..

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) :)

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

希望这可以帮助!

于 2012-05-19T17:12:07.883 回答
3

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

这是我为 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);
        }
    }
}

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

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

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

于 2012-03-30T04:05:33.357 回答
2

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

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

您可以订阅此事件,或在需要时自己调用 JSHint 代码(非常短)。

于 2012-03-02T09:47:24.877 回答
2

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

对于 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();
    });
  }
});

对于 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);
});
于 2015-03-19T09:36:58.283 回答