回调函数与DOM事件
原文:http://dean.edwards.name/weblog/2009/03/callbacks-vs-events/
先看如下代码:
document.addEventListener("DOMContentLoaded", function() {
console.log("Init: 1");
DOES_NOT_EXIST++; // error
}, false);
document.addEventListener("DOMContentLoaded", function() {
console.log("Init: 2");
}, false);
你预期当页面加载后,console下会出现什么结果?
结果是这样的:
Init: 1 Uncaught ReferenceError: DOES_NOT_EXIST is not defined Init: 2
重点在于: 两个事件监听函数都执行了.虽然在第一个事件监听函数中出现了错误,但并没有阻止第二个函数的执行.
问题来了.
接下来我们基于回调函数系统的代码.使用jQuery:
$(document).ready(function() {
console.log("Init: 1");
DOES_NOT_EXIST++; // error
});
$(document).ready(function() {
console.log("Init: 2");
});
此时你从console下看到了什么?没错,是这样:
Init: 1
Uncaught ReferenceError: DOES_NOT_EXIST is not defined
好吧,这意味着回调函数系统是极其脆弱的.一旦任何一个回调函数中抛出了异常,则余下的回调函数序列将不再执行.
在实际开发环境中,这意味着一个写得烂的插件可以令其他插件无法初始化.
Dojo与jQuery有相同的问题,而YUI包装了try/catch机制,它会让回调函数中的错误悄悄地被捕获:
YAHOO.util.Event.onDOMReady(function() {
console.log("Init: 1");
DOES_NOT_EXIST++; // this will throw an error
});
YAHOO.util.Event.onDOMReady(function() {
console.log("Init: 2");
});
所以你将在console看到如下结果:
Init: 1 Init: 2
几近完美的初始化! 貌似没什么好担心的了,除了那些你看不到的错误.
那该如何解决呢?
下面的解决方案是这样的: 使用回调函数混合真正的事件调度.
我们可以触发一个自定义事件,并在该事件的监听函数中,迂回地执行回调函数.
因为每个事件处理程序都有它自己的上下文,所以,即便在事件处理函数内发生了错误,也不会影响到我们的回调函数系统了.
回调函数序列中的每一个函数都将被执行.
这里是代码:
var currentHandler;
if (document.addEventListener) {
document.addEventListener("fakeEvents", function() {
// execute the callback
currentHandler();
}, false);
var dispatchFakeEvent = function() {
var fakeEvent = document.createEvent("UIEvents");
fakeEvent.initEvent("fakeEvents", false, false);
document.dispatchEvent(fakeEvent);
};
} else { // MSIE
document.documentElement.fakeEvents = 0; // an expando property
document.documentElement.attachEvent("onpropertychange", function(event) {
if (event.propertyName == "fakeEvents") {
// execute the callback
currentHandler();
}
});
dispatchFakeEvent = function(handler) {
// fire the propertychange event
document.documentElement.fakeEvents++;
};
}
var onLoadHandlers = [];
function addOnLoad(handler) {
onLoadHandlers.push(handler);
};
window.onload = function() {
for (var i = 0; i < onLoadHandlers.length; i++) {
currentHandler = onLoadHandlers[i];
dispatchFakeEvent();
}
};
这次,执行结果当然又是我们预期的了:
Init: 1 Uncaught ReferenceError: DOES_NOT_EXIST is not defined Init: 2
回调函数与DOM事件的更多相关文章
- C#将C++动态库的回调函数封装成事件
关于C#调用C++动态库的文章很多,调用动态库中回调函数的方法也不在少数.但大多数调用回调函数的方法依然保留了C++的语法特点. 比如有一段C++的回调函数代码,为了表达它的意思,我把注释也粘贴了进来 ...
- DOM事件机制
前言 本文主要介绍DOM事件级别.DOM事件模型.事件流.事件代理和Event对象常见的应用,希望对你们有些帮助和启发! 本文首发地址为GitHub博客,写文章不易,请多多支持与关注! 一.DOM事件 ...
- VC++ 回调函数及使用方法(转)
转载:http://blog.csdn.net/vsooda/article/details/7435801 转载:http://blog.csdn.net/lincyang/article/deta ...
- SetTimer 与 回调函数
在控制台应用程序中,SetTimer的函数原型为: UINT_PTR SetTimer( HWND hWnd, // handle to window UINT_PTR nIDEvent, // ti ...
- 关于js中的回调函数callback
来源于:http://www.jianshu.com/p/6bc353e5f7a3 前言 其实我一直很困惑关于js 中的callback,困惑的原因是,学习中这块看的资料少,但是平时又经常见,偶尔复制 ...
- 关于 js 中的回调函数 callback
本文写于1年前 曾经的学习文章如今拿出来分享 前言 其实我一直很困惑关于js中的callback,困惑的原因是,学习中这块看的资料少,但是平时又经常见,偶尔复制一下前人代码,功能实现了也就不再去追其原 ...
- python异步回调函数的实现
#coding:utf-8 from socket import * import time #简单的服务器程序 监听用户连接,接收用户发来的信息,并返回反馈 def main(): HOST = & ...
- 关于js中的回调函数callback,通俗易懂
前言 其实我一直很困惑关于js 中的callback,困惑的原因是,学习中这块看的资料少,但是平时又经常见,偶尔复制一下前人代码,功能实现了也就不再去追其原由,这么着,这个callback的概念就越来 ...
- 原生js判断css3动画过度(transition)结束 transitionend事件 以及关键帧keyframes动画结束(animation)回调函数 animationEnd 以及 css 过渡 transition无效
上图的 demo 主要讲的 是 css transition的过渡回调函数transitionend事件: css3 的时代,css3--动画 一切皆有可能: 传统的js 可以通过回调函数判断动画 ...
随机推荐
- Hadoop2.2.0 安装笔记
在Youtube上找到靠谱的教程:http://www.youtube.com/watch?v=WN2tJk_oL6E 同时把作者的教程下载下来放在百度云盘上了:http://pan.baidu.co ...
- Difference between Pragma and Cache-control headers?
Pragma is the HTTP/1.0 implementation and cache-control is the HTTP/1.1 implementation of the same c ...
- POJ 3494 Largest Submatrix of All 1’s(最大全1子矩阵)
题目链接:http://poj.org/problem?id=3494 题意:给出一个01的矩阵,找出一个面积最大的全1矩阵. 思路:用h[i][j]表示从位置(i,j)向上连续1的最大长度.之后枚举 ...
- 大数据工具——Splunk
Splunk是机器数据的引擎.使用 Splunk 可收集.索引和利用所有应用程序.服务器和设备(物理.虚拟和云中)生成的快速移动型计算机数据 .从一个位置搜索并分析所有实时和历史数据. 使用 Splu ...
- C#操作文件
c# 操作txt文件 # 操作txt文件 c#创建文本 private const string FILE_NAME = "ErroLog.txt"; public static ...
- UVa 11093 Just Finish it up
从第一个加油站开始枚举起点,如果到第i个加油站油量不够的话,那么1~i个加油站都不可能是起点. 将第i+1个加油站作为起点继续枚举. 比如说,第一个加油站开始最多跑到第5个加油站,那么第二个加油站不可 ...
- POJ 1456 (贪心+并查集) Supermarket
有n件商品,每件商品有它的利润和售出的最后期限,问能够得到的最大利润是多少 这道题和 HDU 1789 Doing Homework again 几乎一模一样,只不过这个是求最的扣分,本题是求最大利润 ...
- .net4.0下 解决asp.net中“从客户端中检测到有潜在危险的Request.Form值”的错误
asp.net 2.0 通常解决办法 方案一: 将.aspx文件中的page项添加ValidateRequest="false" ,如下: <%@ Page Validate ...
- WEBUS2.0 In Action - 搜索操作指南 - (1)
上一篇:WEBUS2.0 In Action - 索引操作指南(2) | 下一篇:WEBUS2.0 In Action - 搜索操作指南(2) 1. IQueriable中内置的搜索功能 在Webus ...
- 使用phantomjs生成网站快照
http://phantomjs.org/ 昨天(2013/08/12)在代码区看到一个生成站点快照的代码,看了半天才发现,作者仅仅贴出来业务代码,最核心的生成快照图片的代码反而没有给出来. 以前记得 ...