2012-02-29 59 views
23

我使用ACE編輯器進行交互的JavaScript編輯更改處理有效。當我將編輯器設置爲JavaScript模式時,ACE會自動確定代碼是否有效,如果不是,則會顯示錯誤消息和行號。確定是否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 
}); 

有沒有更好的辦法,一些無證API中的JS模式,詢問是否有任何錯誤?

+0

我對ACE沒有太多瞭解,但可以解釋爲什麼使用eval? – hradac 2012-02-29 20:51:03

+0

@hradac比這更好,[我會告訴你](http://phrogz.net/JS/d3-playground/)(正在進行)的工作。 – Phrogz 2012-02-29 21:38:33

+0

我正在做類似的事情,也希望得到答案。每次運行Eval都太昂貴了。 – AndrewKS 2012-03-30 02:41:08

回答

2

ACE使用JsHint內部(在worker),正如你可以在文件中看到有發出一個事件:

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

您可以subscribe此事件,或自己撥打JSHint代碼(這是很短)在需要時。

+1

訂閱這個事件聽起來像個好主意,所以我不會爲每次編輯解析它兩次,並且還因爲require(「../ narcissus/jsparse」)'返回null。任何有關發佈會話的對象的想法?編輯?會議?用代碼顯示如何訂閱來編輯你的答案肯定會讓你接受。 :) – Phrogz 2012-03-02 17:45:09

+0

有關注冊的建議? – Phrogz 2012-03-19 16:08:26

3

我發現了一個解決方案,可能比遍歷DOM更快。編輯器的會話有一個可以使用的getAnnotations方法。每個註釋都有一個類型來顯示它們是否是錯誤的。

這是我如何設置我的回調爲上「變」

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

據我所知,還有其他兩種類型的註解:「警告」和「信息」,以防萬一你也想檢查一下。

我不停的軌道,在全球工作的透水代碼(當然,回調函數的範圍之外),因爲經常會有在註釋列表中的代碼錯誤,但不是。在這種情況下,當評估錯誤的代碼時,它會代碼並評估舊代碼。

雖然看起來像兩個evals會比較慢,在我看來,像表現並不壞,迄今。

25

當註釋更改時,當前會話觸發onChangeAnnotation事件。之後

一套新的註釋可以如下

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

似乎這樣的伎倆來檢索。它返回一個JSON對象,其中密鑰,數組爲,值爲數組可能有多個對象,具體取決於每行是否有多個註釋。

的結構如下(從螢火複製 - 對於測試腳本,我寫)

// 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編輯會話,當註釋更改!

希望這會有所幫助!

+0

這是很好的信息,但它不能立即檢測到問題:註釋(包括錯誤)在編輯器的「change」回調中不可用;您必須等到異步驗證發生。 – Phrogz 2012-05-19 17:43:22

+0

編輯答案!希望它現在有所幫助! – hkrish 2012-05-20 17:41:27

+0

getAnnotations()格式已更改...它現在是一個對象數組。 – DrFriedParts 2012-12-24 01:48:16

2

我發現您可以訂閱工人事件王牌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); 
});