回调函数与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);

你预期当页面加载后,console下会出现什么结果?

结果是这样的:

Init: 1

Uncaught ReferenceError: DOES_NOT_EXIST is not defined

Init: 2


重点在于: 两个事件监听函数都执行了.虽然在第一个事件监听函数中出现了错误,但并没有阻止第二个函数的执行.

问题来了.

接下来我们基于回调函数系统的代码.使用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 });

此时你从console下看到了什么?没错,是这样:

Init: 1
Uncaught ReferenceError: DOES_NOT_EXIST is not defined

好吧,这意味着回调函数系统是极其脆弱的.一旦任何一个回调函数中抛出了异常,则余下的回调函数序列将不再执行.

在实际开发环境中,这意味着一个写得烂的插件可以令其他插件无法初始化.

Dojo与jQuery有相同的问题,而YUI包装了try/catch机制,它会让回调函数中的错误悄悄地被捕获:


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看到如下结果:

Init: 1

Init: 2


几近完美的初始化! 貌似没什么好担心的了,除了那些你看不到的错误.

那该如何解决呢?

下面的解决方案是这样的: 使用回调函数混合真正的事件调度.

我们可以触发一个自定义事件,并在该事件的监听函数中,迂回地执行回调函数.

因为每个事件处理程序都有它自己的上下文,所以,即便在事件处理函数内发生了错误,也不会影响到我们的回调函数系统了.

回调函数序列中的每一个函数都将被执行.

这里是代码:


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

这次,执行结果当然又是我们预期的了:

Init: 1

Uncaught ReferenceError: DOES_NOT_EXIST is not defined

Init: 2


回调函数与DOM事件

时间: 2024-11-08 13:14:02

回调函数与DOM事件的相关文章

【JS】DOM事件模型

DOM事件模型主要包含4个方面的内容,分别是: 事件流 主流浏览器的事件模型 事件对象 注册与移除事件监听器 下面一一了解下: 首先,什么是DOM?文档对象模型(DOM)是表示文档(比如HTML和XML)和访问.操作构成文档的各种元素的应用程序接口(API).一般的,支持Javascript的所有浏览器都支持DOM. 在DOM眼中,HTML跟XML一样是一种树形结构的文档,<html>是根(root)节点,<head>.<title>.<body>是<

DOM事件与jQuery事件的是非纠葛

在javascript和JQuery之中,都有事件的处理方式,在我们编写程序实现某些功能的时候,我们会发现使用原生的DOM事件与JQuery中封装的事件都能实现同样的效果,那么也许我们会认为他们之间的区别不是很大,甚至说基本没有区别.这种观点是错误的,其实在事件函数的底层设计时,他们赋予元素的事件属性是通过不同的事件绑定机制来实现的. 我们先从表面理解:我们都知道,JQuery是javascript的一个函数库,他是基于javascript原生设计的.就是说JQuery中的事件,都是通过java

观察者模式 -&gt; dom事件 / 自定义事件 / Promise 我的理解

观察者模式(Observer) 又称作为发布-订阅模式或消息机制,定义了一种依赖关系,解决了主体对象与观察者对象之间通讯和耦合的问题; 观察者模式例子 引用于<JavaScript设计模式> var Observer = (function(){ var _messages = {}; // 监听信息容器 return { /** * 注册监听信息接口 * @param {String} type 监听信息类型 * @param {Function} fn 对应的回调函数 */ regist:

DOM事件机制

前言 本文主要介绍DOM事件级别.DOM事件模型.事件流.事件代理和Event对象常见的应用,希望对你们有些帮助和启发! 本文首发地址为GitHub博客,写文章不易,请多多支持与关注! 一.DOM事件级别 DOM级别一共可以分为四个级别:DOM0级.DOM1级.DOM2级和DOM3级.而DOM事件分为3个级别:DOM 0级事件处理,DOM 2级事件处理和DOM 3级事件处理.由于DOM 1级中没有事件的相关内容,所以没有DOM 1级事件. 1.DOM 0级事件 el.onclick=functi

回调函数模型设计

Javascript中,回调函数是基于事件轮询实现事件驱动的主要表现形式,回调函数的设计并不难,这里简单介绍两种情况:带参数与不带参数. 不带参数: function sing(callback){ callback(); } sing(function(){ console.log("无参数"); }); //“无参数” sing函数执行时,执行callback函数,这里执行里面的匿名函数,这里提醒一下,无论声明式函数.表达式函数.还是匿名函数作为参数效果是一样的,在Js里,函数作为

回调函数(callback)学习笔记

1.stack overflow 上大神的描述(浏览的网页没记住): A "callback" is any function that is called by another function which takes the first function as a parameter. 2.看了几天的介绍,自己关于回调的简单理解: 1)为了干成某件事,自己建立模块A,然后在A里有一个函数f1负责具体实现某项功能: 2)来自其他地方的模块B已经具备A需要的部分基本功能,B里有个函数 

关于js中的回调函数callback,通俗易懂

前言 其实我一直很困惑关于js 中的callback,困惑的原因是,学习中这块看的资料少,但是平时又经常见,偶尔复制一下前人代码,功能实现了也就不再去追其原由,这么着,这个callback的概念就越来越混乱,因为你总感觉它是你Ajax请求后调用的那个函数,又感觉它是你某一个函数中的形参而已,而当你有一天看到一点关于Node.js的代码后你会更加崩溃,因为你会发现很多的callback,但是这么着下去肯定是不行的,因为很多的东西如果只是知道概念和理论,没有实践出结果,没有思考和感受,这些东西永远不

前端基本知识(四):JS的异步模式:1、回调函数;2、事件监听;3、观察者模式;4、promise对象

JavaScript语言将任务的执行模式可以分成两种:同步(Synchronous)和异步(Asychronous). “同步模式”就是一个任务完成之后,后边跟着一个任务接着执行:程序的执行顺序和排列顺序是一直的:”异步模式”则完全不同,每一个任务都有一个或者多个回调函数(callback),前一个任务结束的时候,不是执行下一个任务,二十执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务顺序不一致的,异步的. 在浏览器端,耗时时间长的操作都应该异步执行,避免浏览器数去

JS的三种使用方式/CSS的三种使用方式/JS中的DOM事件模型/JS中匿名函数的书写及调用/媒体查询@media的三种使用方式

一.JS的三种使用方式 1.html标签中内嵌JS(不提倡使用.)                <button onclick="javascript:alert('你真点啊.')" > 有本事点我呀!!!!</button>                                2.HTML页面中直接使用JS:                <script type="text/javascript">