精华内容
下载资源
问答
  • SpringBoot 实现异步事件Event

    千次阅读 多人点赞 2020-01-14 20:48:14
    场景 很多时候当我们完成某些业务后需要给...定义事件Event 创建一个类,继承ApplicationEvent,并重写构造函数。ApplicationEvent是Spring提供的所有应用程序事件扩展类。 public class NoticeEvent extends A...

    场景

    很多时候当我们完成某些业务后需要给用户推送相关消息提醒。对于这种非核心业务功能我们可以拿出来,创建一个事件去异步执行,从而实现核心业务和子业务的解耦。

    实现

    定义事件类 Event

    创建一个类,继承ApplicationEvent,并重写构造函数。ApplicationEvent是Spring提供的所有应用程序事件扩展类。

    public class NoticeEvent extends ApplicationEvent {
    
        private static final Logger logger = LoggerFactory.getLogger(NoticeEvent.class);
    
        /**
         * 接受信息
         */
        private String message;
    
        public NoticeEvent(String message) {
            super(message);
            this.message = message;
            logger.info("add event success! message: {}", message);
        }
    
        public String getMessage() {
            return message;
        }
    }
    

    创建事件监听类 Listener

    创建一个用于监听指定事件的类,需要实现ApplicationListener接口,说明它是一个应用程序事件的监听类。注意这里需要加上@Component注解,将其注入Spring容器中。

    @Component
    public class NoticeListener implements ApplicationListener<NoticeEvent> {
    
        private static final Logger logger = LoggerFactory.getLogger(NoticeListener.class);
    
        @Override
        public void onApplicationEvent(NoticeEvent noticeEvent) {
            logger.info("listener get event, sleep 2 second...");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            logger.info("event message is : {}", noticeEvent.getMessage());
        }
    }
    

    事件发布

    事件发布很简单,只需要使用Spring 提供的ApplicationEventPublisher来发布自定义事件

    @RestController
    @RequestMapping("/event")
    public class EventController {
    
        private static final Logger logger = LoggerFactory.getLogger(EventController.class);
    
        @Autowired
        private ApplicationEventPublisher applicationEventPublisher;
    
        @GetMapping("/notice/{message}")
        public void notice(@PathVariable(name = "message") String message) {
            logger.info("begin >>>>>>");
            applicationEventPublisher.publishEvent(new NoticeEvent(message));
            logger.info("end <<<<<<");
        }
    }
    

    测试

    启动服务,访问接口 http://localhost:8080/event/notice/hello

    [nio-8080-exec-1] o.y.n.event.controller.EventController   : begin >>>>>>
    [nio-8080-exec-1] org.ylc.note.event.event.NoticeEvent     : add event success! message: hello
    [nio-8080-exec-1] org.ylc.note.event.event.NoticeListener  : listener get event, sleep 2 second...
    [nio-8080-exec-1] org.ylc.note.event.event.NoticeListener  : event message is : hello
    [nio-8080-exec-1] o.y.n.event.controller.EventController   : end <<<<<<
    

    执行成功了,但是通过控制台打印信息发现这里并没有异步执行

    异步执行

    默认是没有开启异步的,我们需要手动配置开启异步功能,很简单,只需要在配置类上加上@EnableAsync注解就行了,该注解用于声明启用Spring的异步方法执行功能,需要和@Configuration 注解一起使用,我们可以直接加在启动类上。然后在监听方法上加上@Async注解,说明当前方法使用异步去执行。

    	@Async
        @Override
        public void onApplicationEvent(NoticeEvent noticeEvent) {
            logger.info("listener get event, sleep 2 second...");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            logger.info("event message is : {}", noticeEvent.getMessage());
        }
    

    重启服务,重新访问接口:

    [nio-8080-exec-1] o.y.n.event.controller.EventController   : begin >>>>>>
    [nio-8080-exec-1] org.ylc.note.event.event.NoticeEvent     : add event success! message: hello
    [nio-8080-exec-1] o.y.n.event.controller.EventController   : end <<<<<<
    [         task-1] org.ylc.note.event.event.NoticeListener  : listener get event, sleep 2 second...
    [         task-1] org.ylc.note.event.event.NoticeListener  : event message is : hello
    
    

    可以发现已经实现了异步功能,主线程为nio-8080-exec-1,监听线程为 task-1。从浏览器反应可以看出,接口直接返回了,并没有等监听线程执行完后才返回。

    自定义异步线程池

    开启异步后,会使用Spring内部默认的线程池,我们可以自定义这个线程池。创建配置类(加上@Configuration),实现AsyncConfigurer接口,重写Executor方法。这里我们可以将原先配置在启动类上的@EnableAsync注解放到这个类上。

    @Configuration
    @EnableAsync
    public class AsyncConfig implements AsyncConfigurer {
    
        private final Logger log = LoggerFactory.getLogger(this.getClass());
    
        /**
         * 自定义异步线程池,若不重写会使用默认的线程池
         */
        @Override
        public Executor getAsyncExecutor() {
            ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
            // 核心线程数
            taskExecutor.setCorePoolSize(2);
            // 最大线程数
            taskExecutor.setMaxPoolSize(10);
            // 队列大小
            taskExecutor.setQueueCapacity(15);
            // 线程名的前缀
            taskExecutor.setThreadNamePrefix("async-thread-");
            taskExecutor.initialize();
            return taskExecutor;
        }
    
        /**
         * 捕捉IllegalArgumentException异常
         */
        @Override
        public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
            return new MyAsyncExceptionHandler();
        }
    
        class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
            @Override
            public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
                log.info("TASK Exception message - " + throwable.getMessage());
                log.info("Method name - " + method.getName());
                for (Object param : objects) {
                    log.info("Parameter value - " + param);
                }
            }
        }
    }
    

    重启服务,重新访问接口:

    [nio-8080-exec-1] o.y.n.event.controller.EventController   : begin >>>>>>
    [nio-8080-exec-1] org.ylc.note.event.event.NoticeEvent     : add event success! message: hello
    [nio-8080-exec-1] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService
    [nio-8080-exec-1] o.y.n.event.controller.EventController   : end <<<<<<
    [ async-thread-1] org.ylc.note.event.event.NoticeListener  : listener get event, sleep 2 second...
    [ async-thread-1] org.ylc.note.event.event.NoticeListener  : event message is : hello
    

    控制台中异步线程名变成我们定义的 async-thread-X ,说明配置成功了。

    访问源码

    所有代码均上传至Github上,方便大家访问

    >>>>>> event事件 <<<<<<

    日常求赞

    创作不易,如果各位觉得有帮助,求点赞 支持

    求关注

    俞大仙

    展开全文
  • Python3进程通信之事件Event

    千次阅读 2018-08-23 20:58:08
    进程通信之事件Event ”’ 事件对象multiprocessing.Event-进程之间的状态标记通信。 因为进程不共享数据,子进程是将主进程的数据拷贝一份来执行的并不是同一份数据,所以要将定义的事件作为参数传入函数才可以...

    进程通信之事件Event

    事件对象multiprocessing.Event-进程之间的状态标记通信。因为进程不共享数据,子进程是将主进程的数据拷贝一份来执行的并不是同一份数据,所以要将定义的事件作为参数传入函数才可以正常运行。

    import multiprocessing
    import time
    
    event = multiprocessing.Event()
    
    
    def xiao_fan(event):
        print('生产...')
        print('售卖...')
        # time.sleep(1)
        print('等待就餐')
        event.set()
        event.clear()
        event.wait()
        print('谢谢光临')
    
    
    def gu_ke(event):
        print('准备买早餐')
        event.wait()
        print('买到早餐')
        print('享受美食')
        # time.sleep(2)
        print('付款,真好吃...')
        event.set()
        event.clear()
    
    
    if __name__ == '__main__':
        # 创建进程
        xf = multiprocessing.Process(target=xiao_fan, args=(event,))
        gk = multiprocessing.Process(target=gu_ke, args=(event, ))
        # 启动进程
        gk.start()
        xf.start()
        # time.sleep(2)
    

    F:\win10software\Python36\python36.exe E:/Python1807/llf/进程/进程通信/事件.py
    准备买早餐
    生产…
    售卖…
    等待就餐
    买到早餐
    享受美食
    付款,真好吃…
    谢谢光临
    Process finished with exit code 0

    展开全文
  • 每个 event_base 结构体持有一个事件集合,可以检测以确定哪个事件是激活的。 4.1.1 创建默认的event_base struct event_base *event_base_new(void); 功能:函数会检测环境变量,返回一个event_base的指针,分配...

    一.event_base

    (一) libevent简介与浅谈event_base

    在这里插入图片描述

    1. libevent实际上就是对底层select/poll/epoll等进行了封装,每个event_base都有一种“方法”,该“方法”是select、poll、epoll、kqueue、devpoll、evport、win32。
    2. 使用 libevent 函数之前需要分配一个或者多个 event_base 结构体。每个 event_base 结构体持有一个事件集合,可以检测以确定哪个事件是激活的。
    3. event_base 相当于是一个底座,只要向底座上插入事件,然后不断的监控事件,等待事件发生调用回调函数即可

    (二) event_base的API

    1. 检查event_base后端方法(IO多路复用方法)

    函数声明功能
    const char **event_get_supported_methods(void);返回一个指针 ,指向 libevent 支持的IO多路方法名字数组,这个数组的最后一个元素是NULL
    const char *event_base_get_method(const struct event_base *base);返回 event_base 正在使用的IO多路方法
    enum event_method_feature event_base_get_features(const struct event_base *base);返回 event_base 支持的特征的比特掩码
    //libevent的版本
    printf("Starting Libevent %s. Available methods are:\n", event_get_version());
    
    //检查支持的IO多路方法
    const char **methods = event_get_supported_methods();
    for (int i=0; methods[i] != NULL; ++i) {
    	printf(" %s\n", methods[i]);
    }
    
    struct event_base *base = event_base_new();
    enum event_method_feature f;
    
    if (!base) 
    {
    	puts("Couldn't get an event_base!");
    } 
    else 
    {
    	//返回 event_base 正在使用的IO多路方法
    	printf("Using Libevent with backend method %s\n",event_base_get_method(base));
    	
    	//返回 event_base 支持的特征的比特掩码
    	f = event_base_get_features(base);
    	if ((f & EV_FEATURE_ET)) //支持边沿触发的后端
    		printf(" Edge-triggered events are supported.");
    	if ((f & EV_FEATURE_O1)) //添加、删除单个事件,或者确定哪个事件激活的操作是 O(1)复杂度的后端
    		printf(" O(1) event notification is supported.");
    	if ((f & EV_FEATURE_FDS)) //要求支持任意文件描述符,而不仅仅是套接字的后端
    		printf(" All FD types are supported.");
    }
    

    2. 创建事件根基event_base_new

    struct event_base *event_base_new(void);
    功能:函数会检测环境变量,返回一个event_base的指针,分配并且返回一个新的具有默认设置的 event_base。

    3. 释放事件根基event_base_free

    void event_base_free(struct event_base *base); //释放event_base
    注意:这个函数不会释放当前与 event_base 关联的任何事件,或者关闭它们的套接字 ,或者释放任何指针。应该手动的释放它们

    4. event_base和fork

    int event_reinit(struct event_base *base);
    因为不是所有的安插在event_base的事件在调用fork()之后都可以正常工作,所以,如果在使用fork()或者其他相关系统调用启动一个新的进程之后,要想在子进程中使用base变量,但是又想让该base变量是一个全新的没有安插事件的变量,就应该在子进程中对base调用event_reinit函数进行重新初始化。

    [伪代码]
    	struct event_base* base=event_base_new();
    	
    	//向event_base中安插事件
    	
    	if(fork()) // parent process
    	{
    		continue_runing_parent(base); 
    	}
    	else //child process
    	{
    		event_reinit(base); //重新初始化子进程从父进程继承下来的base
    		continue_runing_child(base);
    	}
    

    5. 设置event_base支持的优先级别个数

    int event_base_priority_init(struct event_base *base, int n_priorities);

    • 功能:给event_base设置共有n_priorities个优先级级别,以便于事件安插在event_base之前可以设置[0, n_priorities-1]级别的优先级
    • 返回值:成功时这个函数返回 0,失败时返回 -1。
    • 参数:
      • base是要修event_base
      • n_priorities是要支持的优先级数目,这个数目至少是 1 。每个新的事件可用的优先级将从 0 (最高) 到 n_priorities-1(最低)。常量 EVENT_MAX_PRIORITIES 表示 n_priorities 的上限。

    默认情况下,与 event_base 相关联的事件的优先级将默认被初始化为 n_priorities / 2


    二.事件循环 event_loop

    一旦创建好事件根基event_base,并且在根基上安插好事件之后,需要对事件循环监控(换句话说就是等待事件的到来,触发事件的回调函数),有两种方式可以达到上面描述的功能,即:event_base_dispatch和event_base_loop

    (一) 事件循环

    方式1:int event_base_dispatch(struct event_base *);

    方式2:int event_base_loop(struct event_base *base, int flags);

    • 参数flags
      • EVLOOP_ONCE:相当于epoll_wait阻塞方式&&只调用一次 ⇒ 当没有事件到来时,程序将一直阻塞在event_base_loop函数;直到有任意一个事件到来时,程序才不会阻塞在event_base_loop,将会继续向下执行。
      • EVLOOP_NONBLOCK:相当于epoll_wait非阻塞方式&&只调用一次 ⇒ 即使没有事件到来,程序也不会阻塞在event_base_loop
      • EVLOOP_NO_EXIT_ON_EMPTY:等价于event_base_dispatch ⇒ 将一直循环监控事件 ⇒ 直到没有已经注册的事件 || 调用了event_base_loopbreak()或 event_base_loopexit()为止

    (二) 终止事件循环

    event_base_dispatch函数退出的三种情况
    当所有的事件都active完毕,此时没有处于未决状态(正在被监听)的事件时
    调用event_base_loopexit(struct event_base*, const struct timeval*)函数
    调用event_base_loopbreak(struct event_base*)函数

    如果想在移除所有已注册的事件之前停止活动的事件循环,可以调用两个稍有不同的函数

    函数声明功能与区别
    int event_base_loopexit(struct event_base *base, const struct timeval *tv);让 event_base 在给定时间之后停止循环。如果 tv 参数为 NULL ,event_base 会立即停止循环,没有延时。如果 event_base 当前正在执行任何激活事件的回调,则回调会继续运行,直到运行完所有激活事件的回调之才退出
    int event_base_loopbreak(struct event_base *base);让 event_base 立即退出循环(即使有其他正在执行任何激活事件的回调)

    (3)转储event_base的状态

    void event_base_dump_events(struct event_base *base, FILE *f);
    功能:将event_base上安插的事件情况,写入到绑定的文件中

    FILE *fp = fopen("event_base_stat.txt","a"); 
    event_base_dump_events(base, fp); //将base的状态,保存到文件中
    fclose(fp);
    

    三.事件event

    (一) 事件状态转换图

    在这里插入图片描述
    event的使用步骤

    在base上安装、监控event的流程
    struct event* ev=event_new(base,fd,what,cb,arg)创建事件,事件处于非未决/初始化状态
    event_add(ev,NULL); //使事件处于未决状态
    event_base_dispatch(base); //循环检测事件,事件发生时触发回调函数
    event_free(ev);释放事件
    event_base_free(base);释放event_base

    信号事件signalEvent、事件event的使用步骤对比
    可以看到:

    1. signalEvent和event的类型一样,都是struct event*
    2. 使用过程也完全一样
    3. 唯一的不同点,是在创建struct event*对象时不同,分别为evsignal_new/event_new
    4. 警告:不要在信号事件上设置超时,这可能是不被支持的。[待修正:真是这样的吗?]
    信号事件signalEvent事件event
    struct event *signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base);struct event* ev=event_new(base,fd,what,cb,arg)
    event_add(signal_event, NULL)event_add(ev,NULL);

    (二) 事件event相关API

    1.创建事件: event_new \ event_assign

    创建并初始化struct event类型的事件变量,根据创建的位置分为堆/栈

    创建位置函数原型
    堆区struct event *event_new(struct event_base *base, evutil_socket_t fd, short what, void (*cb)(evutil_socket_t, short, void *), void *arg);
    栈区int event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, short events, void (*callback)(evutil_socket_t, short, void *), void *arg)
    event_newevent_assign
    功能试图在堆上分配和构造一个用于 base 的新的event在栈上已经初始化好struct event类型的变量,使用event_assign函数对其进行初始化
    使用步骤struct event * ev;struct event ev;
    ev=event_new(_,_,_,_,__);event_assign(&ev,_,_,_,_,__);
    警告不要对已经在 event_base 中处于未决状态的事件调用 event_assign(如果已经初始化和成为未决的,需要调用event_assign之前需要调用event_del)

    参数介绍

    • fd:如果fd非负,表示被观察其读写事件的文件
    • cb/arg:事件激活时,调用的回调函数cb和参数arg
    • what:
      • EV_TIMEOUT 超时
      • EV_READ 可读
      • EV_WRITE 可写
      • EV_SIGNAL 用于实现信号检测,请看下面的 “构造信号事件”节
      • EV_PERSIST 事件是“持久的”
      • EV_ET 边沿触发事件

    [重点]关于事件持久性:EV_PERSIST

    (1)是否设置EV_PERSIST标志的本质区别:事件从active状态结束后,将变成 [ 未决状态 / 非未决状态 ] ?

    是否设置EV_PERSIST持久标志?事件在进入active状态并且回调函数执行完毕后,事件状态从active状态变成什么状态?
    设置未决状态(事件仍然被监听)
    未设置非未决状态(事件已经不被监听)

    (2)分析程序,深刻的体会设置/不设置EV_PERSIST的区别

    输入任意字符,按回车后,代码的执行结果
    情况1:不设置EV_PERSIST持久标志事件被触发后,事件状态进入非未决状态,此时没有被监听的事件 ==> 导致程序执行callback后,直接退出
    情况2:设置EV_PERSIST持久标志事件被触发后,事件状态进入未决状态,此时事件仍然被监听;并且缓冲区的数据一直存在 ==> 导致程序一直执行callback函数,不断的打印横线
    void event_cb(evutil_socket_t fd, short what, void *arg)
    {
      printf("____________________\n");
    }
    
    int main()
    {
      struct event_base* base = event_base_new();
      
      int fd = 0;
      //情况1:不设置EV_PERSIST持久标志
      struct event* ev = event_new(base,fd,EV_TIMEOUT|EV_READ/*|EV_PERSIST*/,event_cb,NULL);
      //情况2:设置EV_PERSIST持久标志
      struct event* ev = event_new(base,fd,EV_TIMEOUT|EV_READ|EV_PERSIST,event_cb,NULL);
    
      event_add(ev,NULL); //使事件处于未决状态
    
      event_base_dispatch(base); //循环检测事件,直到没有要注册的事件或者调用exit/break函数
    
      event_free(ev); // 释放事件 void event_free(struct event *event);
      event_base_free(base);
      return 0;
    }
    

    2.event_add \ event_del

    功能:让事件从非未决状态/未决状态之间切换
    int event_add(struct event *ev, const struct timeval *tv);
    int event_del(struct event *ev);

    3. 带优先级的事件:event_priority_set

    int event_priority_set(struct event *event, int priority); //设置事件event的优先级priority,其中priority属于[0, n_priorities-1]

    设置事件优先级的步骤相关API使用
    1. 创建event_base和eventevent_base_new()、event_new()
    2. 设置event_base支持的[优先级的数目n_priorities]event_base_priority_init(base, n_priorities);
    3. 设置event的优先级event_priority_set(ev, 0);
    4. 将event安插到event_base上

    说明:如果不为事件event设置优先级,则默认的优先级等于 event_base 的优先级数目n_priorities除以2

    4. 手动激活事件: event_active

    void event_active(struct event *ev, int what, short ncalls);
    功能:使没被触发的事件,成为active状态
    重点

    1. 事件不需要已经处于未决状态:即,不调用event_add(ev)的事件ev,也能被event_active触发
    2. 激活事件也不会让它成为未决的激活事件也不会让它成为未决的:即,事件active后,还是保持未active之前的状态,并不是进入未决状态

    代码案例
    程序执行结果:程序执行一次event_cb函数后,直接退出
    分析原因:调用event_active函数后,事件ev并没有变成“未决状态”,导致此时没有待监控的事件,所以event_base_dispatch函数返回,程序退出

    void event_cb(evutil_socket_t fd, short what, void *arg)
    {
      printf("____________________\n");
    }
    
    int main()
    {
      struct event_base* base = event_base_new();
      
      int fd = 0;
      
      //EV_PERSIST永久监控EV_READ事件
      struct event* ev = event_new(base,fd,EV_TIMEOUT|EV_READ|EV_PERSIST,event_cb,NULL); 
    
      //event_add(ev,NULL);  //不需要通过event_add使事件ev处于未决状态
    
      event_active(ev,EV_READ,0); //触发事件后,事件并没进入未决状态
    
      event_base_dispatch(base);
      event_free(ev);
      event_base_free(base);
      return 0;
    }
    

    5. 一次触发事件event_base_once

    函数原型:int event_base_once(struct event_base *, evutil_socket_t, short, void (*)(evutil_socket_t, short, void *), void *, const struct timeval *);

    1. event_base_once()函数除了不支持EV_SIGNAL或EV_PERSIST外,它与event_new()函数相同
    2. 事件回调函数执行后,libevent内部会将会释放event结构
    3. event_base_once ()插入的事件不能删除/取消 或 手动激活
    展开全文
  • javascript判断是否按回车键 ... onkeypress="enterHandler(event);"/>   function enterHandler(event) { //获取用户单击键盘的“键值” var keyCode = event.keyCode ? event.keyCode : event.which ? event.

    javascript判断是否按回车键

    <input id="chatMsg" name="chatMsg" type="text" size="90" οnkeypress="enterHandler(event);"/>

     

    function enterHandler(event)

    {//获取用户单击键盘的“键值”

    var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;

    //如果是回车键

    if (keyCode == 13){

    sendRequest();}

    }


    onkeyup,onkeydown,onkeypress
    在使用JavaScript做WEB键盘事件侦听捕获时,主要采用onkeypress、onkeydown、onkeyup三个事件进行出来。该三个事件的执行顺序如下:onkeydown > onkeypress >onkeyup。在一般情况下,采用三种键盘事件均可对键盘输入进行有效的响应。当在实际使用中,会发现这几者有些不同的差别。   


    键盘事件包括keydown、kepress和keyup三种,每次敲击键盘都会(依次?)触发这三种事件:


     
           1、keypress事件不能对系统功能键(例如:后退、删除等,其中对中文输入法不能有效响应)进行正常的响应,keydown和onkeyup均可以对系统功能键进行有效的拦截,但事件截获的位置不同,可以根据具体的情况选择不同的键盘事件;


     
           2、keypress事件的keyCode对字母的大小写敏感,而keydown、keyup事件不敏感;


    3、keypress事件的keyCode无法区分主键盘上的数字键和副键盘数字键的,而keydown、keyup的keyCode对主副键盘的数字键敏感。


            keydown和keyup是比较低级的接近于硬件的事件,通俗的理解是这两个事件可以捕获到你敲击了键盘中某个键;而keypress是相对于字符层面的较为高级点的事件,这个事件能够捕捉到你键入了哪个字符。可以这样理解,如果你敲击了A键,keydown和keyup事件只是知道你敲击了A键,它并不知道你敲的是大写的A(你同时按下了Shift键)还是敲的是小写a,它是以"键"为单位,你敲入了大写的A,它只是当成你敲下了shift和A两个键而已,但是keypress可以捕捉到你是敲入的大写的A还是小写的a.   
      
            在介绍Prototype中Event对象前先介绍一下浏览器中的事件模型,浏览器中的事件主要有HTML事件、鼠标事件和键盘事件,前两种事件比较好理解,这里主要解释一下键盘事件以及它在IE和firefox中的区别.   
      
            还要理解一个概念是键盘中的键分为字符(可打印)键和功能键(不可打印),功能键包括Backspace, Enter, Escape, the arrow keys, Page Up, Page Down, and F1 through F12 等   
      
            下面说一下键盘事件的具体使用方法,   
      
            键盘事件的event对象中包含一个keyCode属性,IE中只有这一个属性,当为keydown和keyup 事件是,keycode属性表示你具体按下的键(也称为virtual keycode),当捕捉的是keypress事件时keyCode属性指的是你键入的字符(character code)   
      
            在firefox中情况有些不同,event对象包含一个keyCode属性和一个charCode属性,keydown和keyup事件的时候,keyCode表示的就是你具体按的键,charCode为0;当捕捉的是keypress事件时,keyCode为0,charCode指的是你按下的字符   
      
            注意:功能键不会触发keypress事件,因为keypress对应的就是可打印的字符,但是有一点IE和FF 中的区别,你按下一个字符键的同时按下alt键,在IE中不触发keypress事件,但是在FF中可触发,我发现在IE中按下ctrl键的时候只有按下q键会触发事件其他的要么不会触发事件,要么被浏览器IE自身捕获了,例如你按下ctrl_A,全选某个东西,你按ctrl_S保存文件,但是在FF中就好多了,事件都是先传递到网页,再向外传递   
      
            鉴于IE和FF中的区别,如果你比较懒的话,建议只使用keydow和keyup事件,这两种事件的使用在IE和FF中基本上没有区别,也不要捕获ctrl_A等被浏览器定义为快捷键的事件   

            键盘事件event对象还有三个其他的属性altKey, ctrlKey, and shiftKey 来判断你按下一个键的时候是否按下了alt等键,这三个属性使用比较简单,三种事件都可以使用,也不存在IE和FF的兼容性问题


    Netscape/Firefox/Opera中不支持 window.event.keyCode,需要用event.which代替,IE用event.keCode方法获取当前被按下的键盘按键值,而NetScape/FireFox/Opera用的则是event.which。

    event.which属性的返回值是Number类型,返回触发当前事件时按下的键盘按键或鼠标按钮。

    mousedownmouseup事件中,event.which属性返回的是对应鼠标按钮的映射代码值(相当于event.which)

    keypress事件中,event.which属性返回的是输入的字符的Unicode值(相当于event.charCode)

    keydownkeyup事件中,event.which属性返回的是对应按键的映射代码值(相当于evenet,keyCode)

    验证代码:(链接:http://www.jquery123.com/keypress/)

    <!DOCTYPE html>
    <html>
    <head>
      <style>
    fieldset { margin-bottom: 1em; }
    input { display: block; margin-bottom: .25em; }
    #print-output {
      width: 100%;
    }
    .print-output-line {
      white-space: pre;
      padding: 5px;
      font-family: monaco, monospace;
      font-size: .7em;
    }
     
    </style>
      <script src="http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js"></script>
    </head>
    <body>
      <form>
      <fieldset>
        <label for="target">Type Something:</label>
        <input id="target" type="text" />
      </fieldset>
    </form>
    <button id="other">
      Trigger the handler
    </button>
    <script src="http://api.jquery.com/resources/events.js"></script>
     
    <script>
    var xTriggered = 0;
    $("#target").keypress(function(event) {//keydown、keyup验证方法相同
      if ( event.which == 13 ) {
         event.preventDefault();
       }
       xTriggered++;
       var msg = "Handler for .keypress() called " + xTriggered + " time(s).";
      $.print( msg, "html" );
      $.print( event );
    });
     
    $("#other").click(function() {
      $("#target").keypress();
    });</script>
     
    </body>
    </html>



    展开全文
  • 在我们操作数据库过程中,通常会遇到一些某个时间点操作数据库的问题,例如...你可能会想到通过触发器实现,但是如果是同一张表Insert插入数据后,但是触发器再进行Update更新操作是不行的,所以需要尝试通过Event事件
  • 很多同学对Solidity 中的Event有疑问,这篇文章就来详细的看看Solidity 中Event到底有什么用? 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊、智能合约有所了解,如果你还不了解,...
  • Spring 注解事件Event

    万次阅读 2016-08-28 18:46:03
    String event 从Spring的4.2版本后,开始支持注解来进行事件广播接收,这使得我们非常方便 当然了Spring也支持JMS消息中间件,这个就可以做多个系统集成了,感觉有点偏题了,先看看事件怎么通过注解来开发 基础...
  • 服务端事件EventSource揭秘阅读目录服务端推EventSource规范简析参考资料服务端推服务端推,指的是由服务器主动的向客户端发送消息(响应)。在应用层的HTTP协议实现中,“请求-响应”是一个round trip,它的起点...
  • js自动触发事件&&自定义事件 Event

    千次阅读 2019-08-29 09:22:34
    在有些情况下,我们需要程序逻辑自动触发元素的事件,例如js提供了click(),form提供了reset(),submit()等方法!在jquery中提供了trigger()方法帮助我们自动触发事件,原理是什么呢?接下来让我们一探究竟! 一、...
  • Python---事件Event

    万次阅读 2018-05-02 14:16:26
    Event用法:event=threading.Event() #设置一个事件实例event.set() #设置标志位event.clear() #清空标志位event.wait() #等待设置标志位红绿灯实例:#红绿灯 '''标志位设定,代表绿灯,直接通行;标志位被清空,...
  • Python 之 pygame 学习(事件 event

    千次阅读 2019-08-09 14:09:43
    本节重点理解 Pygame 里的事件 文章目录一、事件 一、事件 事件 上一个程序中,点击关闭窗口产生一个 QUIT 事件,Pygame 会接受用户的各种操作(比如按键盘,移动鼠标等)产生事件事件随时可能发生,而且...
  • Laravel事件 event

    千次阅读 2016-10-13 18:26:09
    事件是一种常见的观察者模式的应用。简单的来说,就是当...干...。这个当...和干...在Laravel 事件中分别对应: 当(event)...干(listener)... 放置event和listener文件的位置分别是: app/Events app/Listeners ...
  • 网页标题 #d1{ background-color:black; height:300px; color:white; cursor:crosshair;... function fn(e){ //将事件event作为参数传递 var x=e.clientX; //获取鼠标事件的坐标
  • JavaScript事件event对象属性

    千次阅读 2011-12-01 18:55:43
    //event 对象只在事件发生的过程中才有效。  阻止事件默认行为: IE:window.event.returnValue = true FF:e.preventDefault() 阻止事件冒泡行为: IE:win
  • VC线程Thread和事件Event

    千次阅读 2015-04-18 23:00:59
    VC线程Thread和事件Event操作方法: 头文件 class CMyTestService { public: CMyTestService(); virtual ~CMyTestService(); public: DWORD m_dwThreadID;//监听线程ID BOOL m_bThreadRun;//监听线程内,...
  • Spring Event事件通知机制

    万次阅读 多人点赞 2019-03-11 21:10:57
    Spring的事件通知机制是一项很有用的功能,使用事件机制我们可以将相互耦合的代码解耦,从而方便功能的修改与添加。本文我来学习并分析一下Spring中事件的原理。 举个例子,假设有一个添加评论的方法,在评论添加...
  • 阻止默认事件event.preventDefault();

    千次阅读 2020-04-26 16:12:27
    event.preventDefault(); 阻止浏览器默认事件。什么是默认事件,例如浏览器默认右键菜单、a标签默认连接跳转…
  • (干货)vue 事件参数$event

    千次阅读 2020-08-17 23:03:36
    <!... <... <head>...事件简写和事件对象$event</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> window.onload = functi.
  • 无意中发现了一个巨牛的人工智能教程,...一行文本内容会被反序列化成一个event【序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地...
  • Event事件处理机制和原理

    千次阅读 2017-08-03 10:25:56
    一)事件处理机制的原理  事件模型定义了一套标准的生成和处理事件消息的方法,使程序中的对象可以相互交互、通信、保持自身状态和...数据对象的发出者,称之为事件发送者(Event dispatcher)。同时,接受事件
  • React Event 事件系统

    千次阅读 2018-09-22 10:51:13
    React事件 React 标准化了事件对象,因此在不同的浏览器中都会有相同的属性。 组件createClass后创建的是许多方法组成的对象。组件中使用的方法分为React自有的方法与用户定义的方法。其中React自有方法是组件...
  • c# 事件Event)机制

    万次阅读 多人点赞 2018-10-24 18:43:56
    重新熟悉一下委托和事件。 通过事件使用委托 事件在类中声明且生成,且通过使用同一个类或其他类中的委托与事件处理程序关联。包含事件的类用于发布事件。这被称为 发布器(publisher) 类。其他接受该事件的类...
  • python--事件event简单用法

    千次阅读 2019-05-08 15:59:42
    在并发编程中,涉及到了时间event的使用,首先要先了解到event上线程threading模块中的一个类。具体的用法有: event.set() # 设置标志位 event.wait() #等待设置标志位 event.clear() # 清除标志位 废话不说,看...
  • Event参数可以帮到你!!! 开发工具与关键技术:DreamWeaver Event参数 作者:听民谣的老猫(博客) 撰写时间:2019/1/16 15:30 在JavaScript学习过程中接触到的Event参数,在后期学习中对Event参数的使用和理解...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 754,761
精华内容 301,904
关键字:

事件event