alert()實現原理的探索!(c++底層機制我也不懂啊!)


作者:貘喫饃香
鏈接:http://www.zhihu.com/question/20963787/answer/34123046
來源:知乎
著作權歸作者所有,轉載請聯繫作者獲得授權

  1. JS BOM api 中 alert 的實現
  2. GUI 中模態窗口阻塞其他代碼運行原理
一個個來說

第一個比較簡單。
首先它是目標平臺的包裝函數,也就是非JS原生 API。

這需要調用JS 引擎的包裝方法來作,也就是JS引擎(一般是C++ Lib)會給出一些用來把目標平臺業務API(函數)包裝爲可使用JS語法調用的機制。
比如 Qt C++ 方法:
QScriptValue ScriptBinding::alert(QScriptContext *context, QScriptEngine *interpreter)
{
    ...

    QMessageBox messageBox;
    messageBox.information(NULL,
                           "App Message:",
                           message,
                           QMessageBox::Yes, QMessageBox::Yes);

    return QScriptValue::UndefinedValue;
}
這個方法實際上是調用了一個GUI模態窗口,實現基於 Qt 的 alert 提示。
然後使用JS 引擎相關方法把它包裝到JS的全局對象中。
// 獲取JS引擎
QScriptEngine engine = new QScriptEngine();

// 獲取JS全局環境
globalObject = engine->globalObject();
QScriptValue nativeMathod;

// 引擎包裝一個新方法,執行這個方法時候將調用 C++ 的alert函數
nativeMathod = engine->newFunction(ScriptBinding::alert);

// 把這個包裝好的alert方法放到JS全局環境中
globalObject.setProperty("alert", nativeMathod, QScriptValue::ReadOnly | QScriptValue::Undeletable);
這樣,C++ 實現的 alert 方法就被包裝到 js 中。在js 全局調用 alert 就可以談出對話框。

第二個比較複雜,不好用既有代碼表述。

儘量簡單的來描述下。
基於 GUI 的系統呢,其 UI 部分會有個 EventLoop(真不想用這個詞兒……) 或者 MessageLoop 線程來收發消息。畢竟用戶操作基本上是異步的,總得響應操作事件,這個不難理解吧。
如果,開啓模態窗口後續操作禁止了,那麼有幾種可能性:
  1. 執行線程終止
  2. 執行線程被 sleep
  3. 無視MessageLoop(也就是不響應用戶操作事件)
前兩個可想而知,執行線程終止或sleep,那就啥都別幹了,好比同步AJAX 鎖死界面了。
第三個也是鎖死界面,但是有緩。
爲啥呢,起碼 開啓的 alert UI 可以自己內部開個消息線程來接替主消息循環接收用戶輸入響應就好了。
都知道的,消息線程其實就是個有條件退出的死循環。等用戶點擊確定啊,關閉啊,它就到達退出條件了,然後把主消息循環恢復,主界面又可以響應用戶操作了,然後關閉(擦除)自身UI就好了。
這裏有個小細節,就是模態窗口阻塞代碼的事兒。這不是絕對的(這裏說的是瀏覽器JS實現的模態)。
比如:
BX9015: setTimeout 和 setInteval 在各瀏覽器中被對話框阻塞的情況不同

細節上來說,這可能取決於alert內消息循環實現,這個 while(true) 是否處於主代碼執行之前,還是另開了線程來異步循環的。
如:
主UI代碼
....
alert() 
  內部 
  while(true){
    ....
  }
主 UI 後續代碼
一旦如此實現,可見,在alert 的內部消息循環有條件退出前,主代碼會被阻塞。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章