回调函数与DOM事件
原文:http://dean.edwards.name/weblog/2009/03/callbacks-vs-events/
先看如下代碼:
1 document.addEventListener("DOMContentLoaded", function() { 2 console.log("Init: 1"); 3 DOES_NOT_EXIST++; // error 4 }, false); 5 6 document.addEventListener("DOMContentLoaded", function() { 7 console.log("Init: 2"); 8 }, false);你預(yù)期當(dāng)頁(yè)面加載后,console下會(huì)出現(xiàn)什么結(jié)果?
結(jié)果是這樣的:
Init: 1Uncaught ReferenceError: DOES_NOT_EXIST is not definedInit: 2重點(diǎn)在于: 兩個(gè)事件監(jiān)聽函數(shù)都執(zhí)行了.雖然在第一個(gè)事件監(jiān)聽函數(shù)中出現(xiàn)了錯(cuò)誤,但并沒有阻止第二個(gè)函數(shù)的執(zhí)行.
?
問題來了.
?
接下來我們基于回調(diào)函數(shù)系統(tǒng)的代碼.使用jQuery:
1 $(document).ready(function() { 2 console.log("Init: 1"); 3 DOES_NOT_EXIST++; // error 4 }); 5 6 $(document).ready(function() { 7 console.log("Init: 2"); 8 });?
此時(shí)你從console下看到了什么?沒錯(cuò),是這樣:
Init: 1 Uncaught ReferenceError: DOES_NOT_EXIST is not defined?
好吧,這意味著回調(diào)函數(shù)系統(tǒng)是極其脆弱的.一旦任何一個(gè)回調(diào)函數(shù)中拋出了異常,則余下的回調(diào)函數(shù)序列將不再執(zhí)行.
在實(shí)際開發(fā)環(huán)境中,這意味著一個(gè)寫得爛的插件可以令其他插件無法初始化.
Dojo與jQuery有相同的問題,而YUI包裝了try/catch機(jī)制,它會(huì)讓回調(diào)函數(shù)中的錯(cuò)誤悄悄地被捕獲:
1 YAHOO.util.Event.onDOMReady(function() { 2 console.log("Init: 1"); 3 DOES_NOT_EXIST++; // this will throw an error 4 }); 5 6 YAHOO.util.Event.onDOMReady(function() { 7 console.log("Init: 2"); 8 });所以你將在console看到如下結(jié)果:
Init: 1Init: 2幾近完美的初始化! 貌似沒什么好擔(dān)心的了,除了那些你看不到的錯(cuò)誤.
那該如何解決呢?
下面的解決方案是這樣的: 使用回調(diào)函數(shù)混合真正的事件調(diào)度.
我們可以觸發(fā)一個(gè)自定義事件,并在該事件的監(jiān)聽函數(shù)中,迂回地執(zhí)行回調(diào)函數(shù).
因?yàn)槊總€(gè)事件處理程序都有它自己的上下文,所以,即便在事件處理函數(shù)內(nèi)發(fā)生了錯(cuò)誤,也不會(huì)影響到我們的回調(diào)函數(shù)系統(tǒng)了.
回調(diào)函數(shù)序列中的每一個(gè)函數(shù)都將被執(zhí)行.
這里是代碼:
1 var currentHandler; 2 3 if (document.addEventListener) { 4 document.addEventListener("fakeEvents", function() { 5 // execute the callback 6 currentHandler(); 7 }, false); 8 9 var dispatchFakeEvent = function() { 10 var fakeEvent = document.createEvent("UIEvents"); 11 fakeEvent.initEvent("fakeEvents", false, false); 12 document.dispatchEvent(fakeEvent); 13 }; 14 } else { // MSIE 15 16 document.documentElement.fakeEvents = 0; // an expando property 17 18 document.documentElement.attachEvent("onpropertychange", function(event) { 19 if (event.propertyName == "fakeEvents") { 20 // execute the callback 21 currentHandler(); 22 } 23 }); 24 25 dispatchFakeEvent = function(handler) { 26 // fire the propertychange event 27 document.documentElement.fakeEvents++; 28 }; 29 } 30 31 var onLoadHandlers = []; 32 function addOnLoad(handler) { 33 onLoadHandlers.push(handler); 34 }; 35 36 window.onload = function() { 37 for (var i = 0; i < onLoadHandlers.length; i++) { 38 currentHandler = onLoadHandlers[i]; 39 dispatchFakeEvent(); 40 } 41 };?這次,執(zhí)行結(jié)果當(dāng)然又是我們預(yù)期的了:
Init: 1Uncaught ReferenceError: DOES_NOT_EXIST is not definedInit: 2?
轉(zhuǎn)載于:https://www.cnblogs.com/fangzhaolee/p/3719384.html
總結(jié)
以上是生活随笔為你收集整理的回调函数与DOM事件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: border-collapse:coll
- 下一篇: 帝国CMS附件大小限制