我正在使用ACE编辑器进行交互式JavaScript编辑。当我将编辑器设置为JavaScript模式时,ACE会自动确定代码是否有效,错误消息和行号不会突出显示。
在change
事件处理程序期间,我想在我尝试eval()
之前检测ACE是否认为代码有效。我认为我可以做到的唯一方法是:
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){}
});
然而:
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中,询问是否有任何错误?
答案 0 :(得分:25)
当注释发生变化时,当前会话将触发 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编辑会话中所有注释的列表!
希望这有帮助!
答案 1 :(得分: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);
}
}
}
据我所知,注释还有另外两种类型:“警告”和“信息”,以防万一你也想检查它们。
我一直跟踪在全局(在回调函数范围之外)工作的以前的代码,因为通常会在代码中出现错误,但不会在注释列表中出现错误。在这种情况下,当评估错误代码时,它将代码并评估旧代码。
虽然看起来两个版本的速度会慢一些,但在我看来,到目前为止表现并不差。
答案 2 :(得分:2)
Ace在内部使用JsHint
(在worker中),正如您在文件中看到的那样,发生了一个事件:
this.sender.emit("jslint", lint.errors);
您可以subscribe参加此活动,或者在需要时自己调用JSHint代码(它很短)。
答案 3 :(得分: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代码,订阅'错误'并且' 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);
});