确定 JavaScript 语法在 ACE 的更改处理程序中是不是有效
Posted
技术标签:
【中文标题】确定 JavaScript 语法在 ACE 的更改处理程序中是不是有效【英文标题】:Determine if JavaScript syntax is valid in change handler of ACE确定 JavaScript 语法在 ACE 的更改处理程序中是否有效 【发布时间】:2012-03-19 08:29:53 【问题描述】:我正在使用 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)
);
但是:
-
依靠 UI 中具有特定类的元素的存在似乎非常脆弱,但更重要的是,
在
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 中,询问是否有任何错误?
【问题讨论】:
我对 ACE 了解不多,但您能解释一下为什么要使用 eval 吗? @hradac 比这更好,I'll show you(正在进行中)工作。 我正在做类似的事情,也希望得到答案。 eval 每次运行都太昂贵了。 【参考方案1】:当前会话在注解更改时触发 onChangeAnnotation 事件。
之后,新的一组注解可以按如下方式检索
var annotations = editor.getSession().getAnnotations();
似乎可以解决问题。它返回一个 JSON 对象,其中 row 作为 key,一个数组作为 value。 value 数组可能有多个对象,具体取决于每一行是否有多个注解。
结构如下(抄自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://***.com/a/684692/1405348 for annot.hasOwnProperty(key) :)
当注释发生变化时,应该给你当前 Ace 编辑会话中所有注释的列表!
希望这会有所帮助!
【讨论】:
这是很好的信息,但它无助于立即发现问题:注释(包括错误)在编辑器的change
回调中不可用;您必须等到异步验证发生。
编辑了答案!希望现在有帮助!
getAnnotations() 格式发生了变化……它现在是一个对象数组。
应该是annot[key].row
,而不是annot[key][0].row
。
@OnurYILDIRIM Annotations 对象的每一行都有一个数组“rownumber : [ annotation1, annotation2 ]”;见上文。因为每行可以有多个注释。 (或者现在 API 是否发生了变化?) 编辑:我没有在上面看到 DrFriedParts 的评论。我会检查并纠正它。【参考方案2】:
我找到了一个可能比遍历 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'ing 错误代码时,它将是 code 并 eval 旧代码。
虽然看起来两个 eval 会慢一些,但在我看来,性能并没有那么糟糕,到目前为止。
【讨论】:
【参考方案3】:Ace 在内部使用JsHint
(在worker 中),正如您在文件中看到的那样,发出了一个事件:
this.sender.emit("jslint", lint.errors);
你可以subscribe这个事件,或者在需要的时候自己调用JSHint代码(很短)。
【讨论】:
订阅该事件听起来是个好主意,这样我就不会为每次编辑解析两次,还因为require("../narcissus/jsparse")
为我返回了null
。关于该会话发出什么对象的任何想法?编辑?会议?使用显示如何订阅的代码编辑您的答案肯定会赢得您的接受。 :)
关于注册什么有什么建议吗?【参考方案4】:
我发现您可以在 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);
);
【讨论】:
在最近的版本中,事件已重命名:error
=> annotate
/ ok
=> terminate
。以上是关于确定 JavaScript 语法在 ACE 的更改处理程序中是不是有效的主要内容,如果未能解决你的问题,请参考以下文章
如何使用自定义模式在 Ace Editor 中集成语法检查?