精华内容
下载资源
问答
  • 事件驱动编程

    2014-03-26 13:59:00
    一种语义词语。 动词:代表过去发生的事情。 事件既是技术架构概念,也是业务概念(funny event)。 以事件驱动编程模型称为事件驱动架构
  • 主要为大家详细介绍了Javascript事件驱动编程的相关资料,通过经典案例向大家介绍Javascript事件驱动编程,需要的朋友可以参考下
  • 主要介绍了Node.js中的事件驱动编程详解,本文主要讲解理论性知识,如什么是事件驱动编程、什么是闭包、闭包如何帮助异步编程等知识,需要的朋友可以参考下
  • 事件驱动 基本概念 窗口/组件 事件 消息(队列) 事件响应(服务处理程序) 调度算法 进程/线程 非阻塞I/O 程序的执行可以看成对CPU,内存,IO资源一次占用 现代操作系统支持...

    事件驱动

    基本概念

    • 窗口/组件

    • 事件

    • 消息(队列)

    • 事件响应(服务处理程序)

    • 调度算法

    • 进程/线程

    • 非阻塞I/O

    • 程序的执行可以看成对CPU,内存,IO资源一次占用

    • 现代操作系统支持多任务,可以分时复用上述资源.

    1. 为什么采用事件驱动模型?

    事件驱动模型也就是我们常说的观察者,或者发布-订阅模型;理解它的几个关键点:

    • 首先是一种对象间的一对多的关系;最简单的如交通信号灯,信号灯是目标(一方),行人注视着信号灯(多方);

    • 当目标发送改变(发布),观察者(订阅者)就可以接收到改变;

    • 观察者如何处理(如行人如何走,是快走/慢走/不走,目标不会管的),目标无需干涉;所以就松散耦合了它们之间的关系。

    2. 代码执行流程

    在传统的或“过程化”的应用程序中,应用程序自身控制了执行哪一部分代码和按何种顺序执行代码。从第一行代码执行程序并按应用程序中预定的路径执行,必要时调用过程。
    在事件驱动的应用程序中,代码不是按照预定的路径执行-而是在响应不同的事件时执行不同的代码片段。事件可以由用户操作触发、也可以由来自操作系统或其它应用程序调度算法的消息触发、甚至由应用程序本身的消息触发。这些事件的顺序决定了代码执行的顺序,因此应用程序每次运行时所经过的代码的路径都是不同的。

    3. 事件驱动模型

    在UI编程中,常常要对鼠标点击进行相应,首先如何获得鼠标点击呢?

    方式一:创建一个线程,该线程一直循环检测是否有鼠标点击,那么这个方式有以下几个缺点:

    1. CPU资源浪费,可能鼠标点击的频率非常小,但是扫描线程还是会一直循环检测,这会造成很多的CPU资源浪费;如果扫描鼠标点击的接口是阻塞的呢?
    2. 如果是堵塞的,又会出现下面这样的问题,如果我们不但要扫描鼠标点击,还要扫描键盘是否按下,由于扫描鼠标时被堵塞了,那么可能永远不会去扫描键盘;
    3. 如果一个循环需要扫描的设备非常多,这又会引来响应时间的问题;所以,该方式是非常不好的。

    方式二:就是事件驱动模型目前大部分的UI编程都是事件驱动模型,如很多UI平台都会提供onClick()事件,这个事件就代表鼠标按下事件。事件驱动模型大体思路如下:

    1. 有一个事件(消息)队列;

    2. 鼠标按下时,往这个队列中增加一个点击事件(消息);

    3. 有个循环,不断从队列取出事件,根据不同的事件,调用不同的函数,如onClick()、onKeyDown()等;

    4. 事件(消息)一般都各自保存各自的处理函数指针,这样,每个消息都有独立的处理函数;如图:

     

    4. 事件驱动处理库

    • select

    • poll

    • epoll

    • libev

    5.效率比较 

    让我们用例子来比较和对比一下单线程、多线程以及事件驱动编程模型。下图展示了随着时间的推移,这三种模式下程序所做的工作。这个程序有3个任务需要完成,每个任务都在等待I/O操作时阻塞自身。阻塞在I/O操作上所花费的时间已经用灰色框标示出来了。

     

    在单线程同步模型中,任务按照顺序执行。如果某个任务因为I/O而阻塞,其他所有的任务都必须等待,直到它完成之后它们才能依次执行。这种明确的执行顺序和串行化处理的行为是很容易推断得出的。如果任务之间并没有互相依赖的关系,但仍然需要互相等待的话这就使得程序不必要的降低了运行速度。

    在多线程版本中,这3个任务分别在独立的线程中执行。这些线程由操作系统来管理,在多处理器系统上可以并行处理,或者在单处理器系统上交错执行。这使得当某个线程阻塞在某个资源的同时其他线程得以继续执行。与完成类似功能的同步程序相比,这种方式更有效率,但程序员必须写代码来保护共享资源,防止其被多个线程同时访问。多线程程序更加难以推断,因为这类程序不得不通过线程同步机制如锁、可重入函数、线程局部存储或者其他机制来处理线程安全问题,如果实现不当就会导致出现微妙且令人痛不欲生的bug。

    在事件驱动版本的程序中,3个任务交错执行,但仍然在一个单独的线程控制中。当处理I/O或者其他昂贵的操作时,注册一个回调到事件循环中,然后当I/O操作完成时继续执行。回调描述了该如何处理某个事件。事件循环轮询所有的事件,当事件到来时将它们分配给等待处理事件的回调函数。这种方式让程序尽可能的得以执行而不需要用到额外的线程。事件驱动型程序比多线程程序更容易推断出行为,因为程序员不需要关心线程安全问题。

    当我们面对如下的环境时,事件驱动模型通常是一个好的选择:

    程序中有许多任务,而且…
    任务之间高度独立(因此它们不需要互相通信,或者等待彼此)而且…
    在等待事件到来时,某些任务会阻塞。
    当应用程序需要在任务间共享可变的数据时,这也是一个不错的选择,因为这里不需要采用同步处理。

    网络应用程序通常都有上述这些特点,这使得它们能够很好的契合事件驱动编程模型。

    事件驱动机制跟消息驱动机制相比

    消息驱动和事件驱动很类似,都是先有一个事件,然后产生一个相应的消息,再把消息放入消息队列,由需要的项目获取。他们的区别是消息是谁产生的

    消息驱动:鼠标管自己点击不需要和系统有过多的交互,消息由系统(第三方)循环检测,来捕获并放入消息队列。消息对于点击事件来说是被动产生的,高内聚。

    事件驱动:鼠标点击产生点击事件后要向系统发送消息“我点击了”的消息,消息是主动产生的。再发送到消息队列中。

     

    事件:按下鼠标,按下键盘,按下游戏手柄,将U盘插入USB接口,都将产生事件。比如说按下鼠标左键,将产生鼠标左键被按下的事件。

    消息:当鼠标被按下,产生了鼠标按下事件,windows侦测到这一事件的发生,随即发出鼠标被按下的消息到消息队列中,这消息附带了一系列相关的事件信息,比如鼠标哪个键被按了,在哪个窗口被按的,按下点的坐标是多少?如此等等。

    注意:

    1. 要理解事件驱动和程序,就需要与非事件驱动的程序进行比较。实际上,现代的程序大多是事件驱动的,比如多线程的程序,肯定是事件驱动的。早期则存在许多非事件驱动的程序,这样的程序,在需要等待某个条件触发时,会不断地检查这个条件,直到条件满足,这是很浪费cpu时间的。而事件驱动的程序,则有机会释放cpu从而进入睡眠态(注意是有机会,当然程序也可自行决定不释放cpu),当事件触发时被操作系统唤醒,这样就能更加有效地使用cpu.
    2. 再说什么是事件驱动的程序。一个典型的事件驱动的程序,就是一个死循环,并以一个线程的形式存在,这个死循环包括两个部分,第一个部分是按照一定的条件接收并选择一个要处理的事件,第二个部分就是事件的处理过程。程序的执行过程就是选择事件和处理事件,而当没有任何事件触发时,程序会因查询事件队列失败而进入睡眠状态,从而释放cpu。
    3. 事件驱动的程序,必定会直接或者间接拥有一个事件队列,用于存储未能及时处理的事件。
    4. 事件驱动的程序的行为,完全受外部输入的事件控制,所以,事件驱动的系统中,存在大量这种程序,并以事件作为主要的通信方式。
    5. 事件驱动的程序,还有一个最大的好处,就是可以按照一定的顺序处理队列中的事件,而这个顺序则是由事件的触发顺序决定的,这一特性往往被用于保证某些过程的原子化。
    6. 目前windows,linux,nucleus,vxworks都是事件驱动的,只有一些单片机可能是非事件驱动的。


    事件模式耦合高,同模块内好用;消息模式耦合低,跨模块好用。事件模式集成其它语言比较繁琐,消息模式集成其他语言比较轻松。事件是侵入式设计,霸占你的主循环;消息是非侵入式设计,将主循环该怎样设计的自由留给用户。如果你在设计一个东西举棋不定,那么你可以参考win32的GetMessage,本身就是一个藕合度极低的接口,又足够自由,接口任何语言都很方便,具体应用场景再在其基础上封装成事件并不是难事,接口耦合较低,即便哪天事件框架调整,修改外层即可,不会伤经动骨。而如果直接实现成事件,那就完全反过来了。

     

    什么是数据驱动编程

    正题

    作者在介绍Unix设计原则时,其中有一条为“表示原则:把知识叠入数据以求逻辑质朴而健壮”。结合之前自己的一些经验,我对这个原则很有共鸣,所以先学习了数据驱动编程相关的内容,这里和大家分享出来和大家一起讨论。

    核心

    数据驱动编程的核心出发点是相对于程序逻辑,人类更擅长于处理数据。数据比程序逻辑更容易驾驭,所以我们应该尽可能的将设计的复杂度从程序代码转移至数据。

    真的是这样吗?让我们来看一个示例。假设有一个程序,需要处理其他程序发送的消息,消息类型是字符串,每个消息都需要一个函数进行处理。第一印象,我们可能会这样处理: 

    void msg_proc(const char *msg_type, const char *msg_buf) 
    { 
        if (0 == strcmp(msg_type, "inivite")) 
        { 
            inivite_fun(msg_buf); 
        } 
        else if (0 == strcmp(msg_type, "tring_100")) 
        { 
            tring_fun(msg_buf); 
        } 
        else if (0 == strcmp(msg_type, "ring_180")) 
        { 
            ring_180_fun(msg_buf); 
        } 
        else if (0 == strcmp(msg_type, "ring_181")) 
        { 
            ring_181_fun(msg_buf); 
        } 
        else if (0 == strcmp(msg_type, "ring_182")) 
        { 
            ring_182_fun(msg_buf); 
        } 
        else if (0 == strcmp(msg_type, "ring_183")) 
        { 
            ring_183_fun(msg_buf); 
        } 
        else if (0 == strcmp(msg_type, "ok_200")) 
        { 
            ok_200_fun(msg_buf); 
        }
    
        。。。。。。 
        else if (0 == strcmp(msg_type, "fail_486")) 
        { 
            fail_486_fun(msg_buf); 
        } 
        else 
        { 
            log("未识别的消息类型%s\n", msg_type); 
        } 
    } 


    上面的消息类型取自sip协议(不完全相同,sip协议借鉴了http协议),消息类型可能还会增加。看着常常的流程可能有点累,检测一下中间某个消息有没有处理也比较费劲,而且,没增加一个消息,就要增加一个流程分支。

    按照数据驱动编程的思路,可能会这样设计: 

    typedef void (*SIP_MSG_FUN)(const char *);
    
    typedef struct __msg_fun_st 
    { 
        const char *msg_type;//消息类型 
        SIP_MSG_FUN fun_ptr;//函数指针 
    }msg_fun_st;
    
    msg_fun_st msg_flow[] = 
    { 
            {"inivite", inivite_fun}, 
            {"tring_100", tring_fun}, 
            {"ring_180", ring_180_fun}, 
            {"ring_181", ring_181_fun}, 
            {"ring_182", ring_182_fun}, 
            {"ring_183", ring_183_fun}, 
            {"ok_200", ok_200_fun},
    
            。。。。。。 
            {"fail_486", fail_486_fun} 
    };
    
    void msg_proc(const char *msg_type, const char *msg_buf) 
    { 
        int type_num = sizeof(msg_flow) / sizeof(msg_fun_st); 
        int i = 0;
    
        for (i = 0; i < type_num; i++) 
        { 
            if (0 == strcmp(msg_flow[i].msg_type, msg_type)) 
            { 
                msg_flow[i].fun_ptr(msg_buf); 
                return ; 
            } 
        } 
        log("未识别的消息类型%s\n", msg_type); 
    } 

     

    数据驱动优势

    1、可读性更强,消息处理流程一目了然。

    2、更容易修改,要增加新的消息,只要修改数据即可,不需要修改流程。

    3、重用,第一种方案的很多的else if其实只是消息类型和处理函数不同,但是逻辑是一样的。下面的这种方案就是将这种相同的逻辑提取出来,而把容易发生变化的部分提到外面。

    隐含在背后的思想

    很多设计思路背后的原理其实都是相通的,隐含在数据驱动编程背后的实现思想包括:

    1、控制复杂度。通过把程序逻辑的复杂度转移到人类更容易处理的数据中来,从而达到控制复杂度的目标。

    2、隔离变化。像上面的例子,每个消息处理的逻辑是不变的,但是消息可能是变化的,那就把容易变化的消息和不容易变化的逻辑分离。

    3、机制和策略的分离。和第二点很像,本书中很多地方提到了机制和策略。上例中,我的理解,机制就是消息的处理逻辑,策略就是不同的消息处理(后面想专门写一篇文章介绍下机制和策略)。

    数据驱动可以用来做什么:

    如上例所示,它可以应用在函数级的设计中。

    同时,它也可以应用在程序级的设计中,典型的比如用表驱动法实现一个状态机(后面写篇文章专门介绍)。

    也可以用在系统级的设计中,比如DSL(这方面我经验有些欠缺,目前不是非常确定)。

    它不是什么:

    1、 它不是一个全新的编程模型:它只是一种设计思路,而且历史悠久,在unix/linux社区应用很多;

    2、它不同于面向对象设计中的数据:“数据驱动编程中,数据不但表示了某个对象的状态,实际上还定义了程序的流程;OO看重的是封装,而数据驱动编程看重的是编写尽可能少的代码。”

    书中的值得思考的话:

    数据压倒一切。如果选择了正确的数据结构并把一切组织的井井有条,正确的算法就不言自明。编程的核心是数据结构,而不是算法。——Rob Pike

    程序员束手无策。。。。。只有跳脱代码,直起腰,仔细思考数据才是最好的行动。表达式编程的精髓。——Fred Brooks

    数据比程序逻辑更易驾驭。尽可能把设计的复杂度从代码转移至数据是个好实践。——《unix编程艺术》作者。

     

    转载自:学时网 » 事件驱动编程、消息驱动编程、数据驱动编程

    展开全文
  • Javascript事件驱动编程

    千次阅读 2015-12-25 14:10:38
    Javascript事件驱动编程 基本概述  JS是采用事件驱动的机制来响应用户操作的,也就是说当用户对某个html元素进行操作的时候,会产生一个时间,该时间会驱动某些函数来处理。 PS:这种方式和Java GUI中的事件...

    Javascript事件驱动编程

    基本概述

        JS是采用事件驱动的机制来响应用户操作的,也就是说当用户对某个html元素进行操作的时候,会产生一个时间,该时间会驱动某些函数来处理。

    PS:这种方式和Java GUI中的事件监听机制很像,都是需要注册监听,然后再处理监听,只不过实现的方式不同而已。

     

    可以参考w3school文档:

    http://www.w3school.com.cn/jsref/dom_obj_event.asp

    http://www.w3school.com.cn/tags/html_ref_eventattributes.asp


    事件驱动原理

    事件源:产生事件的地方(html元素)

    事件:点击/鼠标操作/键盘操作等等

    事件对象:当某个事件发生时,可能会产生一个事件对象,该事件对象会封装好该事件的信息,传递给事件处理程序

    事件处理程序:响应用户事件的代码


    案例:

    <html>
    	<head>
    		<script type="text/javascript">
    			function test1(e){
    				window.alert("x=" + e.clientX + " y=" + e.clientY);
    			}
    			function test2(e){
    				window.alert("x=" + e.clientX + " y=" + e.clientY);
    			}
    			function test3(e){
    				window.alert(new Date().toLocaleString());
    			}
    			function test4(e){
    				if(e.value == "red"){
    					div1.style.backgroundColor = "red";
    				} else if (e.value == "black"){
    					div1.style.backgroundColor = "black";
    				}
    			}
    		</script>
    	</head>
    	<body>
    		<input type="button" οnclick="test1(event)" value="button1">
    		<input type="button" οnmοuseοver="test2(event)" value="button2">
    		<input type="button" οnclick="test3(event)" value="button3">
    		<div id="div1" style="width: 400px; height: 300px; background-color: red"></div>
    		<input type="button" οnclick="test4(this)" value="red">
    		<input type="button" οnclick="test4(this)" value="black">
    	</body>
    </html>


    事件编程操作分析

               ①确定事件并为其绑定一个函数

               ②书写绑定的函数

               ③处理数据

    JS事件分类

    鼠标事件 

    click dblclick mousedown mouseout mouseover mouseup mousemove等

    键盘事件 

    keydown keypress keyup等

    HTML事件 

    window的onload unload error abort 文本框的select change等

    其他事件

    页面中有些特殊对象运行过程中产生的事件

     

    案例1:监听鼠标点击事件,并能够显示鼠标点击的位置x,y

    <html>
         <head>
         <script>
         function test1(e){
             window.alert("x="+e.clientX+"y="+e.clientY);
         }
         </script>
         </head>
         <body οnmοusedοwn="test1(event)">
         </body>
    </html>

    点击浏览器之后,显示坐标(有些浏览器可能无效)


    案例2:点击按钮,图片变成红色,黑色

    方法:JS访问内部css

    //js如何访问css属性,来改变外观
    <html>
        <head>
        <script>
            function test3(e){
               var pic=document.getElementById("pic");
               if(e.value=="红色"){
                   pic.style.backgroundColor="red";
               }
               else if(e.value=="黑色"){
                    pic.style.backgroundColor="black";
                }
          }
        </script>
        </head>
        <body >
            <div id="pic" style="border:1;background-color:red;width:300px;height:300px"></div>
            <input type="button" οnclick="test3(this)" value="红色">
            <input type="button" οnclick="test3(this)" value="黑色">
        </body>
    </html>

    方法:JS访问外部css(这方法不一定适用于所有浏览器)

    event2.css

    .style {
        border:1;
        background-color:red;
        width:300px;
        height:300px;
    }

    event2.html

    <html>
        <head>
        <script>
            function test3(e){
                //取连接的第一个css文件的内容用0
                var ocssRules=document.styleSheets[0].rules;
                //从ocssRules取出你希望的样式
                var style=ocssRules[0];//这里面的0表示event2.css文件中第一个规则
                if(e.value=="黑色"){
                    style.style.backgroundColor="black";
                 }
                 else if(e.value=="红色"){
                     style.style.backgroundColor="red";
                 }
            }
        </script>
        </head>
        <body>
            <div class="style"></div>
            <input type="button" οnclick="test3(this)" value="红色">
            <input type="button" οnclick="test3(this)" value="黑色">
          </body>
    </html>

    案例3区分当前浏览器的内核是什么?(区分出ie6/7/8/  火狐等)

    <script language="javascript">
         if(window.XMLHttpRequest)
         { //Mozilla, Safari, IE7,IE8  
        	  	if(!window.ActiveXObject)
            {	 // Mozilla, Safari,  
             	alert('Mozilla, Safari');  
         	}
             else
             {  
             	alert('IE7 .8');  
         	}  
     	  }
          else 
          {  
         	 alert('IE6');  
     	  } 
    </script>

    案例4一个事件可以被多个函数监听

    <html>
        <head>
        function test(e){
            window.alert("fss");
        }
        function test1(e){
            window.alert("sfdsdf");
        }
        </script>
        </head>
        <body>
            <div class="style"></div>
            <input type="button" οnclick="test(this),test1(this)" value="红色">
        </body>
    </html>

    案例5:防止用户通过点击鼠标右键菜单拷贝网页内容,选择网页内容

    <html>
    	<script type="text/javascript">
    		function test(){
    		    //window.alert("没有菜单");
    		    return false;
    	    }
    	    function test2(){
    		    //window.alert("全选不行");
    		    return false;
    	    }	
        </script> 
        </head> 
        <!--body元素响应oncontextmenu,onselectstart事件 -->
        <body οncοntextmenu="return test()" onselectstart="return test2()"> 	
    	    内容
        </body>
    </html>


    综合案例:简单的计算器

    <html>
    	<head>
    		<script>
    			function calc(event){
    				// test 
    				//window.alert(event.value);
    				var val = new String(event.value);
    				// clear space
    				val = val.trim();
    				var res = document.getElementById("res");
    				// clear
    				if(val == "clear"){
    					res.value = "";
    				}
    
    				// back
    				if(val == "back"){
    					res.value = res.value.substring(0, res.value.length - 1);
    				}
    
    				//  power
    				if(val == "power"){
    					val = "p";
    				}
    				// add val to text
    				if(val.length == 1 && val != "="){
    					res.value = res.value + val;
    				}
     
    				// calc result
    				if(val == "="){
    					var arr;
    					var result;
    					// power
    					if(res.value.indexOf("p") != -1){
    						arr = res.value.split("p");
    						//window.alert(arr);
    						 result = Math.pow(parseFloat(arr[0]) ,parseFloat(arr[1]));
    						//window.alert(res);
    						res.value = result;
    					} 			
    					// plus
    					if(res.value.indexOf("+") != -1){
    						arr = res.value.split("+");
    						//window.alert(arr);
    						 result = parseFloat(arr[0]) + parseFloat(arr[1]);
    						//window.alert(res);
    						res.value = result;
    					} else if(res.value.indexOf("-") != -1){
    						// minus
    						arr = res.value.split("-");
    						//window.alert(arr);
    						result = parseFloat(arr[0]) - parseFloat(arr[1]);
    						//window.alert(res);
    						res.value = result;
    					} else if(res.value.indexOf("*") != -1){
    						// multiply
    						arr = res.value.split("*");
    						//window.alert(arr);
    						result = parseFloat(arr[0]) * parseFloat(arr[1]);
    						//window.alert(res);
    						res.value = result;
    					} else if(res.value.indexOf("/") != -1){
    						// division
    						arr = res.value.split("/");
    						//window.alert(arr);
    						result = parseFloat(arr[0]) / parseFloat(arr[1]);
    						//window.alert(res);
    						res.value = result;
    					} else if(res.value.indexOf("%") != -1){
    						// module
    						arr = res.value.split("%");
    						//window.alert(arr);
    						result = parseFloat(arr[0]) % parseFloat(arr[1]);
    						//window.alert(res);
    						res.value = result;
    					}
    				}	
    			}
    		</script>
    	</head>
    	<body>
    		<table border="1px" cellpadding="10px" cellspacing="5px" align="center">
    			<tr align="center">
    				<td colspan="4"><input type="text" id="res" size="35px" value="" style="text-align:right;"/></td>
    			</tr>
    			<tr align="center">
    				<td><input type="button" value="power" οnclick="calc(this)"/></td>
    				<td><input type="button" value="clear" οnclick="calc(this)"/></td>
    				<td colspan="2"><input type="button" value="      back      " οnclick="calc(this)"/></td>
    			</tr>
    			<tr align="center">
    				<td><input type="button" value="   1   " οnclick="calc(this)"/></td>
    				<td><input type="button" value="   2   " οnclick="calc(this)"/></td>
    				<td><input type="button" value="   3   " οnclick="calc(this)"/></td>
    				<td><input type="button" value="   +   " οnclick="calc(this)"/></td>
    			</tr>
    			<tr align="center">
    				<td><input type="button" value="   4   " οnclick="calc(this)"/></td>
    				<td><input type="button" value="   5   " οnclick="calc(this)"/></td>
    				<td><input type="button" value="   6   " οnclick="calc(this)"/></td>
    				<td><input type="button" value="   -    " οnclick="calc(this)"/></td>
    			</tr>
    			<tr align="center">
    				<td><input type="button" value="   7   " οnclick="calc(this)"/></td>
    				<td><input type="button" value="   8   " οnclick="calc(this)"/></td>
    				<td><input type="button" value="   9   " οnclick="calc(this)"/></td>
    				<td><input type="button" value="   *   " οnclick="calc(this)"/></td>
    			</tr>
    			<tr align="center">
    				<td><input type="button" value="   0    " οnclick="calc(this)"/></td>
    				<td><input type="button" value="   =    " οnclick="calc(this)"/></td>
    				<td><input type="button" value="   %    " οnclick="calc(this)"/></td>
    				<td><input type="button" value="   /    " οnclick="calc(this)"/></td>
    			</tr>
    		</table>
    	</body>
    </html>


    综合案例:表格隔行换色+高亮显示

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title>表格隔行换色</title>
    		<script type="text/javascript">
                   function $(id) {
    	             return document.getElementById(id);
                   }
                   function $name(name) {
    	             return document.getElementsByName(name);
                   }
    			window.onload = function () {
    				var vRows =  $("tab1").tBodies[0].rows;
    				// alert(vRows.length);
    				for(var i = 0; i < vRows.length; i++) {
    					// 高亮显示
    					vRows[i].onmouseover = function() {
    						// alert("over");
    						// 设置属性和直接赋值有什么区别
    						//this.backGroundAttr = this.style.backgroundColor;
    						this.setAttribute("bgc", this.style.backgroundColor);
    						// alert(this.backGroundAttr);
    						this.style.backgroundColor = "red";
    					};
    					vRows[i].onmouseout = function() {
    						// alert("out");
    						// this.style.backgroundColor = this.backGroundAttr;
    						this.style.backgroundColor = this.getAttribute("bgc")
    					};
    					// 隔行变色
    					if(i % 2 == 0) {
    						vRows[i].style.backgroundColor = "gray";
    					} else {
    						vRows[i].style.backgroundColor = "lightgray";
    					}
    				}
    			};
    		</script>
    	</head>
    	<body>
    		<table border="1" width="500" height="50" align="center" id="tab1">
    			<thead>
    				<tr>
    					<th>编号</th>
    					<th>姓名</th>
    					<th>年龄</th>
    				</tr>
    			</thead>
    			<tbody>
    				<tr >
    					<td>1</td>
    					<td>张三</td>
    					<td>22</td>
    				</tr>
    				<tr >
    					<td>2</td>
    					<td>李四</td>
    					<td>25</td>
    				</tr>
    				<tr >
    					<td>3</td>
    					<td>王五</td>
    					<td>27</td>
    				</tr>
    				<tr >
    					<td>4</td>
    					<td>赵六</td>
    					<td>29</td>
    				</tr>
    				<tr >
    					<td>5</td>
    					<td>田七</td>
    					<td>30</td>
    				</tr>
    				<tr >
    					<td>6</td>
    					<td>汾九</td>
    					<td>20</td>
    				</tr>
    			</tbody>
    		</table>
    	</body>
    </html>
    

    综合案例:省市二级联动

    <select name="province" id="province" οnchange="chooseCity(this.value)">
        <option selected="selected" disabled="disabled">---请选择您的省份---</option>
        <option value="0">湖南</option>
        <option value="1">湖北</option>
        <option value="2">广东</option>
    </select>
    <select name="city" id="city">
        <option selected="selected" disabled="disabled">---请选择您的城市---</option>
    </select>
    

    var cities = new Array(3);
    cities[0] = new Array("长沙市","株洲市","湘潭市","衡阳市","邵阳市","岳阳市","常德市","张家界市","益阳市","郴州市","永州市","怀化市","娄底市","湘西土家族苗族自治州");
    cities[1] = new Array("武汉市","黄石市","十堰市","宜昌市","襄樊市","鄂州市","荆门市","孝感市","荆州市","黄冈市","咸宁市","随州市","恩施土家族苗族自治州","仙桃市","潜江市","天门市","神农架林区");
    cities[2] = new Array("广州市","韶关市","深圳市","珠海市","汕头市","佛山市","江门市","湛江市","茂名市","肇庆市","惠州市","梅州市","汕尾市","河源市","阳江市","清远市","东莞市","中山市","潮州市","揭阳市","云浮市");
    
    function $(id) {
    	return document.getElementById(id);
    }
    // 省市二级联动
    function chooseCity(val) {
    	// 获取id为city的结点
    	var cityEle = $("city");
    	// 初始化方法
    	// 1.选项设置为0
    	// cityEle.options = 0;
    	// 2.删除所有子结点
    	for (var i = 0; i < cityEle.childNodes.length;) {
    		// 删除时,数组会自动变小,所以无需自增
    		// window.alert(cityEle.childNodes.length);
    		cityEle.removeChild(cityEle.childNodes[i]);
    	}
    	
    	for(var i = 0; i < cities[val].length; i++) {
    		var cityText = document.createTextNode(cities[val][i]);
    		var cityNode = document.createElement("option");
    		var cityAttr = document.createAttribute("value");
    		cityAttr.value = i;
    		cityNode.setAttributeNode(cityAttr);
    		cityNode.appendChild(cityText);
    		cityEle.appendChild(cityNode);
    	}
    }
    



    常用事件总结

               onsubmit:一般用在表单提交上面,书写的位置在<form>标签里面,而且必须要有返回值

               onload:页面加载的时候使用,绑定的时候写在<body>标签里面,只写一个即可。

              

               onclick:需要使用鼠标进行单击的地方,需要操作哪个元素就绑定到那个元素上面去。

               onfocus:当光标移动到某个地方的时候使用,需要操作哪个元素就绑定到那个元素上面去。

               onblur:当光标移离开某个地方的时候使用,需要操作哪个元素就绑定到那个元素上面去。

               onchange:当用户改变域的内容的时候使用改事件(省市二级联动),需要操作哪个元素就绑定到那个元素上面去。

               ondblclick:鼠标双击某个对象 ,需要操作哪个元素就绑定到那个元素上面去。

              

               onkeydown某个键盘的键被按下,需要操作哪个元素就绑定到那个元素上面去。

               onkeypress某个键盘的键被按下或按住,需要操作哪个元素就绑定到那个元素上面去。

               onkeyup某个键盘的键被松开,需要操作哪个元素就绑定到那个元素上面去。

               上面三个事件一般都是连续使用。用在搜索功能上面!

     

               onmouseover鼠标被移到某元素之,需要操作哪个元素就绑定到那个元素上面去。

               onmousemove鼠标被移动 ,需要操作哪个元素就绑定到那个元素上面去。

               onmouseout鼠标从某元素移开,需要操作哪个元素就绑定到那个元素上面去。


    PSJavaScript中的事件并不止这么一点,用到时查文档就行了,可以用上面给的w3school的文档或者是用《JavaScript权威指南》第6896页及以后的事件处理程序有关内容。

    PS:HTML的文档加载顺序是由上至下的,所以如果将JavaScript脚本写在前面的话,那么有时候因为其访问对象还没加载入浏览器引擎中,而导致无法访问到对应对象,所以建议将脚本<script>元素写至body的最后连续几个子元素,这样是绝对不会出现访问出错问题的。

    PS:当然也可以通过将语句放入onload加载事件中加载,也可以通过在<script>元素上加上refer属性延迟加载。但是最方便、最直接的还是放在html文档尾部。

     

    ----------参考《韩顺平.轻松搞定网页设计(html+css+js)》


    展开全文
  • 一个事件总线框架用于事件驱动编程
  • 关于事件驱动编程

    千次阅读 2017-04-21 14:00:06
    关于事件驱动编程全世界最熟悉事件驱动的程序员应该就是前端工程师了,不管是桌面前端还是web前端都是世界上最熟悉事件驱动的,以web前端为例,我们作业面可以不去想什么面向对象编程,什么jQuery框架咋用,但是为按钮,为...

    关于事件驱动编程

    全世界最熟悉事件驱动的程序员应该就是前端工程师了,不管是桌面前端还是web前端都是世界上最熟悉事件驱动的,以web前端为例,我们作业面可以不去想什么面向对象编程,什么jQuery框架咋用,但是为按钮,为页面元素添加相关事件操作肯定是不可缺少的,而web前端的事件处理机制就是标准的事件驱动机制,为了讲解清楚事件驱动,这里我回顾下页面里事件机制,我们开发页面事件的时候,第一步就是定一事件(定义时间就是在定义一个函数)或者说为事件定义一个动作,并把事件绑定到指定的元素上,如果我们没有触发函数上事件,那么定义好的函数也就不会执行,如果元素上的事件被触发了,定义好的函数才会执行.

    关于浏览器里事件机制实现方案,具体如下:

    首先我要说多线程开发里有一个经典的设计方法,这个方法就是生产—-消费模式,生产—-消费模式特点就是生产者和消费者被一个中间队列分隔开来,不管是生产请求还是消费结果都是通过这个中间队列,这样就可以把生产者和消费者关系解耦,事件实现机制从宏观上和生产—-消费模式类似,这个类似不是指设计思想,而是指沟通双方联系的哪个中间层.

    事件处理的机制里应该有个事件处理器,事件处理器位于元素和事件处理方法的中间位置,我们在定义事件的时候就是等于在实践处理器里定义元素和事件处理方法的关系,当这种对应关系定义好后,事件处理器就会启动一个死循环,这个循环反复检测元素的状态变化,当事件处理器发现,某个状态发生了变化,处理器就会找到相应的事件处理方法,然后执行这个方法.

    传统语言做开发的时候都是按照时间的先后顺序,这么做既可以降低语言的学习成本,也可以让开发代码思路比较容易控制,但是现实场景是复杂的,这种按时间顺序的开发流程并不一定是我们解决现实问题的最佳方式.这就好比我们做一件事情,在做的时候我们会碰到很多问题,由于发生的问题不同,那么这件事情的结果可能就会因为情况的不同而发生变化,如果按照时间顺序的变成方式向做好上面的事情就会让程序变得十分复杂,因为我们要按照时间顺序做出各种不同执行路径,这就是排列组合的办法了,这显然让事情变得复杂了,如果用事件驱动变成方式,我们只要定义好事物的起因,各种不同的过程情况,以及所能得到的结果,换句话说我们首先只要关注实体内容而忽略事务关系问题,而事务关系则是在事件处理器里定义的,当我们发送给事件处理器一个指示信号,处理器就会对应找到某个行为,那么事件驱动编程就简化了程序开发的流程.

    展开全文
  • 这里利用队列实现了一个完整的事件驱动编程过程,模拟了银行排队这一离散事件的发生。
  • 收集了一些Java事件驱动编程相关实例源码,都是来自与国外的一些Java代码,里面注释丰富,不过是英文的。这些实例与事件驱动程序设计有关,比如事件监听、注册和处理、内部类监听器、匿名内部类监听器、处理简单行为...
  • 事件总线样本 关于事件驱动编程的 Medium Post 示例
  • 的libpg 一个用于学习入门事件驱动编程的库
  • 12.队列的应用-事件驱动编程

    千次阅读 2014-05-05 17:27:52
    事件驱动编程简而言之就是应用程序维护一个或多个事件队列,完全以事件队列为主线来设计和编写整个程序。这里利用队列实现了一个完整的事件驱动编程过程,模拟了银行排队这一离散事件的发生。

    1.事件驱动编程

    前面我们提到队列在操作系统中用的非常多,其中一大应用就是基于事件驱动的消息队列机制,熟悉Windows SDK程序设计的对于Windows的消息产生、分发、处理应该不会陌生。

    事件驱动编程简而言之就是应用程序维护一个或多个事件队列,完全以事件队列为主线来设计和编写整个程序。如Windows就是以消息队列为中心来对每个消息进行处理从而实现事件驱动编程(如鼠标、键盘等事件的处理)。


    2.离散事件模拟

    现在为了演示事件驱动编程,我可能并没有能力去构建一个windows消息系统,这里以类似的应用:[银行排队模拟]来演示整个程序。

    银行排队模拟描述如下:

    假设一个银行有4个窗口对外接待客户。由于每个窗口在某一时刻只能接待一个客户,在客户众多的时候需要排队,对于刚进入银行的客户,如果某个窗口正空闲,则可上前办理业务,如果所有窗口都不空闲则排在人数最少的窗口。现在要求模拟银行的某一时间段内的4个窗口的客户排队情况。这里客户到达的时刻和办理业务的时间都是随机的。


    可以看到不同的时刻4个窗口的客户排队情况是不一样的,这个客户排队情况完全是以时间推移来驱动的,那么我们就考虑建立一个基于时间的事件队列,按照事件发生的先后排列事件。这种类似的应用统称为离散事件模拟。


    3.实现方式

    事件队列元素定义如下

    typedef struct
    {
    	int		nOccurTime;	//事件发生时间
    	int		nType;		//事件类型,0-客户到达事件,1、2、3、4-对应窗口客户离开事件
    }JWArrayElem_event;

    窗口队列元素定义如下

    typedef struct
    {
    	int nArriveTime;		//客户到达事件
    	int nDurationTime;		//客户办理业务所需时间
    }JWArrayElem_window;


    为了实现上述离散事件模拟,这里我们建立一个事件队列,4个窗口排队队列。

    初始化上述队列,在事件队列中插入第一个客户到达事件以启动事件驱动。

    开启计时,检测是否有事件要发生。

    如果是客户到达事件,则设置客户办理业务时间,插入到窗口队列中,同时要插入下一个客户到达事件。如果是当前窗口的第一个客户,还要插入一个客户离开事件以驱动当前窗口的客户离开事件。

    如果是客户离开事件,则从对应窗口队列中取出客户并设置下一个客户离开事件,在同一窗口下前一个客户离开事件没有发生之前是不可能发生第二个客户离开事件的。


    4.实际程序

    #include <stdio.h>
    #include <process.h>
    #include <stdlib.h>
    #include <time.h>
    #include <Windows.h>
    
    #include "JWArray.h"
    
    JWArray(event)		*pEventQueue;					//事件队列
    JWArrayElem(event)	eventElem;						//事件元素
    JWArray(window)		*pWindowsQueue[5];				//窗口队列,为了使用方便,下标从1开始
    JWArrayElem(window)	windowElem;						//窗口元素
    int					nCloseTime = 100;				//银行关闭时间
    
    JWArray_BOOL EventCompare(JWArrayElem(event) elem1, JWArrayElem(event) elem2);
    void ShowState(int nCurTime);
    void Init();
    void Clear();
    int  CalcMinWindow();
    void CustomerArrived(int nArriveTime);
    void CustomerLeave(int nCurTime, int iLeave);
    void EventPump();
    void ShowState(int nCurTime);
    
    
    int main(int argc, char *argv[])
    {
    	//开启事件泵
    	EventPump();
    
    	return 0;
    }
    
    /**
     *功能:	事件队列元素比较函数
     *参数:	elem1,elem2 -- 两个事件队列元素
     *返回:	elem1的发生时间小于elem2则返回JWArray_TRUE,否则返回JWArray_FALSE
     *其他:	2014/05/05 By Jim Wen Ver1.0
    **/
    JWArray_BOOL EventCompare(JWArrayElem(event) elem1, JWArrayElem(event) elem2)
    {
    	return elem1.nOccurTime  < elem2.nOccurTime ? JWARRAY_TRUE : JWARRAY_FALSE;
    }
    
    /**
     *功能:	初始化--分配事件队列和窗口队列,在事件队列插入启动的客户到达事件
     *参数:	无
     *返回:	无
     *其他:	2014/05/05 By Jim Wen Ver1.0
    **/
    void Init()
    {
    	int i;
    
    	//分配队列
    	pEventQueue = JWArrayCreate(event)(20, 10);
    	for (i = 1; i < 5; i++)
    	{
    		pWindowsQueue[i] = JWArrayCreate(window)(20, 10);
    	}
    
    	//在事件队列插入第一个客户到达事件
    	eventElem.nOccurTime	= 0;
    	eventElem.nType			= 0;
    
    	JWArrayEnQueue(event)(pEventQueue, eventElem);
    }
    
    /**
     *功能:	清理工作--清理事件队列和窗口队列
     *参数:	无
     *返回:	无
     *其他:	2014/05/05 By Jim Wen Ver1.0
    **/
    void Clear()
    {
    	int i;
    
    	//清理队列
    	JWArrayDestroy(event)(pEventQueue);
    	for (i = 1; i < 5; i++)
    	{
    		JWArrayDestroy(window)(pWindowsQueue[i]);
    	}
    }
    
    /**
     *功能:	计算当前窗口队列前人数最少的窗口号
     *参数:	无
     *返回:	人数最少的窗口队列号
     *其他:	2014/05/05 By Jim Wen Ver1.0
    **/
    int CalcMinWindow()
    {
    	int nLength ;
    	int i ;
    	int nIndex ;
    	
    	nIndex	 = 1;
    	nLength  = JWArrayGetLength(window)(pWindowsQueue[1]);
    	for (i = 2; i <=4 ; i++)
    	{
    		if (JWArrayGetLength(window)(pWindowsQueue[i]) < nLength)
    		{
    			nIndex = i;
    			nLength  = JWArrayGetLength(window)(pWindowsQueue[i]);
    		}
    	}
    
    	return nIndex;
    }
    
    /**
     *功能:	处理客户到达事件
     *参数:	nArriveTime--客户到达的时间
     *返回:	无
     *其他:	2014/05/05 By Jim Wen Ver1.0
    **/
    void CustomerArrived(int nArriveTime)
    {
    	int i;
    	int nDurationtime;			//当前客户办理业务消耗时间
    	int nNextInterTime;			//距离下一个客户到达时间
    
    	//随机生成nDurationtime和nNextInterTime
    	srand( (unsigned)time( NULL ) );
    	nDurationtime = rand() % 30 +1;
    	nNextInterTime = rand() % 5 +1;
    
    	//设置下一个客户到达事件
    	if (nArriveTime + nNextInterTime < nCloseTime)
    	{
    		eventElem.nOccurTime = nArriveTime + nNextInterTime;
    		eventElem.nType = 0;
    
    		JWArrayOrderInsert(event)(pEventQueue, eventElem, EventCompare);
    	}
    
    	//设置当前窗口排列队形
    	i = CalcMinWindow();
    	windowElem.nArriveTime = nArriveTime;
    	windowElem.nDurationTime = nDurationtime;
    	JWArrayEnQueue(window)(pWindowsQueue[i], windowElem);
    
    	//如果是第一个到达客户,插入一个离开事件,否则此后的离开事件在前一个离开事件发生后插入
    	if (JWArrayGetLength(window)(pWindowsQueue[i]) == 1)
    	{
    		eventElem.nOccurTime = nArriveTime + nDurationtime;
    		eventElem.nType = i;
    
    		JWArrayOrderInsert(event)(pEventQueue, eventElem, EventCompare);
    	}
    }
    
    /**
     *功能:	处理客户离开事件
     *参数:	nCurTime--客户离开事件发生时间,iLeave--客户离开事件发生的窗口队列号
     *返回:	无
     *其他:	2014/05/05 By Jim Wen Ver1.0
    **/
    void CustomerLeave(int nCurTime, int iLeave)
    {
    	//window队列出列
    	JWArrayDeQueue(window)(pWindowsQueue[iLeave], NULL);
    
    	//设置下一个客户离开时间
    	if (JWARRAY_FALSE == JWArrayIsEmpty(window)(pWindowsQueue[iLeave]))
    	{
    		JWArrayGetHead(window)(pWindowsQueue[iLeave], &windowElem);
    
    		eventElem.nOccurTime = nCurTime + windowElem.nDurationTime;//注意这里实际离开时间是当前离开事件发生的时间加上下一个客户要办理业务的时间,不能写成下一个客户到达的时间加上下一个客户要办理业务的时间,这是不对的,因为客户到达时不能立即开始办理,要等待!!!
    		eventElem.nType = iLeave;
    
    		JWArrayOrderInsert(event)(pEventQueue, eventElem, EventCompare);
    	}
    }
    
    /**
     *功能:	开启消息泵,依据时间对事件队列处理从而推动整个事件的发生
     *参数:	无
     *返回:	无
     *其他:	2014/05/05 By Jim Wen Ver1.0
    **/
    void EventPump()
    {
    	int i=0;
    
    	Init();
    
    	do 
    	{
    		if (JWARRAY_FALSE != JWArrayGetHead(event)(pEventQueue, &eventElem))
    		{
    			while (eventElem.nOccurTime == i)//处理当前时刻可能同时存在的多个事件
    			{
    				JWArrayDeQueue(event)(pEventQueue, &eventElem);
    
    				if (eventElem.nType == 0)
    				{
    					CustomerArrived(eventElem.nOccurTime);
    				}
    				else
    				{
    					CustomerLeave(i, eventElem.nType);
    				}
    
    				if (JWARRAY_FALSE == JWArrayGetHead(event)(pEventQueue, &eventElem))
    				{
    					break;
    				}
    			}
    		}
    		else
    		{
    			break;
    		}
    
    		ShowState(i++);
    		Sleep(100);
    	} while (1);
    
    	Clear();
    }
    
    /**
     *功能:	显示当前事件队列和各个窗口队列的情况
     *参数:	无
     *返回:	无
     *其他:	2014/05/05 By Jim Wen Ver1.0
    **/
    void ShowState(int nCurTime)
    {
    	system("cls");
    	printf("当前时间:%d\n\n", nCurTime);
    
    	printf("--------------------------------------------------------------------------------\n");
    	printf("事件队列\t");
    	JWArrayTraverse(event)(pEventQueue, JWArrayPrintfElem(event));
    	printf("\n--------------------------------------------------------------------------------\n\n");
    
    	printf("\n--------------------------------------------------------------------------------\n");
    	printf("窗口1\t");
    	JWArrayTraverse(window)(pWindowsQueue[1], JWArrayPrintfElem(window));
    	printf("\n--------------------------------------------------------------------------------\n");
    	printf("窗口2\t");
    	JWArrayTraverse(window)(pWindowsQueue[2], JWArrayPrintfElem(window));
    	printf("\n--------------------------------------------------------------------------------\n");
    	printf("窗口3\t");
    	JWArrayTraverse(window)(pWindowsQueue[3], JWArrayPrintfElem(window));
    	printf("\n--------------------------------------------------------------------------------\n");
    	printf("窗口4\t");
    	JWArrayTraverse(window)(pWindowsQueue[4], JWArrayPrintfElem(window));
    	printf("\n--------------------------------------------------------------------------------\n");
    }

    程序说明:
    1.事件时间单位为秒
    2.假设客户办理业务不超过30秒,相邻两个客户到达时间间隔不超过5秒
    3.银行在100秒后不再允许客户进入
    4.不考虑客户在排队过程中换队的情况
    5.这里对于event队列构建了一个顺序插入函数JWArrayOrderInsert(event)

    程序运行效果如下



    完整事件驱动编程源代码 下载链接
    原创,转载请注明来自 http://blog.csdn.net/wenzhou1219
    展开全文
  • 利巴 从Redis中提取的一个简单的事件驱动编程库。 安装 $ make && sudo make install
  • 关于对事件驱动架构(event drive architecture)和事件驱动编程的理解。 什么是事件? 什么是Event Center 什么是Channel? 事件生产者 事件消费者
  • 部分摘自 ... ... 事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定。它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。另外两种常见的编程范式是
  • 利比 一个简单的事件驱动编程库。
  • ASP.NET 2005第五节 事件驱动编程与回送 视频教学
  • javascript之DOM事件驱动编程

    万次阅读 多人点赞 2012-04-28 14:41:42
    事件驱动编程中的几个核心对象:  事件源:谁发出事件通知,发出消息;也就是事件主体。 事件名称:发出什么样的通知的名称,比如鼠标到我头上了,我被别人点了一下; 事件响应函数:谁对这个这个事件感兴趣,...
  • 在前面的文章中我们简单介绍了事件驱动编程,现在让我们看看真实的代码并介绍EventBus的基础用法。 首先我会参考下图(从EventBus仓库截取的),介绍在事件驱动编程中扮演中心角色的实体们。
  • 这年头nodeJS真是如日中天啊,学前端的要是不知道nodeJS,都不好意思说自己和懂点代码的美工有啥区别,谈到nodeJS就不得不先聊聊它的事件驱动编程风格。究竟什么是事件驱动编程风格呢?在传统编程中,i/o操作和本地...
  • 事件与状态机 事件驱动编程

    千次阅读 2017-05-12 17:53:03
    编程思想 方法
  • ExtJS在事件驱动编程这一块做的是比较好的,下面通过一个简单的例子演示Ext中对事件的处理操作。  在事件驱动编程中,使用ExtJS可以很方便的处理组件的各种事件。为一个组件添加事件的方式是:组件.on(event,fn); ...
  • 摘要 在微嵌入式系统和传感器网络节点中,事件驱动编程是一个受欢迎的模型。尽管事件驱动编程能降低内存开销,但由于它强制使用状态机编程风格,使许多程序难以编写、维护和调试。我们展示了一个新颖的被叫做...
  • 《UML状态图的实用C、C++设计:嵌入式系统的事件驱动编程技术(第二版)》《Practical UML Statecharts in C,C++:Event-Driven Programing for Embedded Systems, Second Edition》
  • 异步事件驱动编程 curses库:目标和使用 警告和间隔计时器 可靠的信号处理 可重入代码、临界区 异步输入 相关的系统调用 alarm、setitimer、getitimer kill、pause sigaction、sigprocmask fcntl、...
  • 并发,同步,异步以及事件驱动编程的相关技术   前言   这篇文章的存在主要是因为本屌才疏学浅,会的东西实在有限,作为本屌的学习之用,如果有前辈能指正一二,本屌将不胜感激!因为本屌一直觉得代码还有API...
  • python下的事件驱动编程

    千次阅读 2013-03-06 17:03:35
    最近用python写一个网络服务的模拟测试程序,先是用同步socket实现了一个简单的server,后来发现要没法添加定时器来定时处理一些任务,于是网上搜索python的异步...我写的模拟测试程序只使用了libevent的事件驱动,下
  • ASP中的事件驱动与回送
  • 理解Python事件驱动编程(Event Loop)

    千次阅读 2017-09-11 17:42:12
    2年前我学习Python的时候只知道并发编程模型只有多进程和多线程,这两个模型的特点都是交由操作系统调度,无法人为控制,而且短板很明显,上下文切换和创建开销都是问题。后来又听说了Python的协程-用户级线程,可以...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 425,906
精华内容 170,362
关键字:

事件驱动编程