鏈接:http://www.zhihu.com/question/20963787/answer/34123046
來源:知乎
著作權歸作者所有,轉載請聯繫作者獲得授權
- JS BOM api 中 alert 的實現
- 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;
}
然後使用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);
第二個比較複雜,不好用既有代碼表述。
儘量簡單的來描述下。
基於 GUI 的系統呢,其 UI 部分會有個 EventLoop(真不想用這個詞兒……) 或者 MessageLoop 線程來收發消息。畢竟用戶操作基本上是異步的,總得響應操作事件,這個不難理解吧。
如果,開啓模態窗口後續操作禁止了,那麼有幾種可能性:
- 執行線程終止
- 執行線程被 sleep
- 無視MessageLoop(也就是不響應用戶操作事件)
第三個也是鎖死界面,但是有緩。
爲啥呢,起碼 開啓的 alert UI 可以自己內部開個消息線程來接替主消息循環接收用戶輸入響應就好了。
都知道的,消息線程其實就是個有條件退出的死循環。等用戶點擊確定啊,關閉啊,它就到達退出條件了,然後把主消息循環恢復,主界面又可以響應用戶操作了,然後關閉(擦除)自身UI就好了。
這裏有個小細節,就是模態窗口阻塞代碼的事兒。這不是絕對的(這裏說的是瀏覽器JS實現的模態)。
比如:
BX9015: setTimeout 和 setInteval 在各瀏覽器中被對話框阻塞的情況不同
細節上來說,這可能取決於alert內消息循環實現,這個 while(true) 是否處於主代碼執行之前,還是另開了線程來異步循環的。
如:
主UI代碼
....
alert()
內部
while(true){
....
}
主 UI 後續代碼