zoukankan      html  css  js  c++  java
  • 事件处理

    事件循环

    JS运行的环境称之为宿主环境。

    • 执行栈:call stack,一个数据结构,用于存放各种函数的执行环境,每一个函数执行之前,它的相关信息会加入到执行栈。函数调用之前,创建执行环境,然后加入到执行栈;函数调用之后,销毁执行环境。

    JS引擎永远执行的是执行栈的最顶部。

    • 异步函数:某些函数不会立即执行,需要等到某个时机到达后才会执行,这样的函数称之为异步函数。比如事件处理函数。异步函数的执行时机,会被宿主环境控制。

    浏览器宿主环境中包含5个线程:

    1. JS引擎:负责执行执行栈的最顶部代码
    2. GUI线程:负责渲染页面
    3. 事件监听线程:负责监听各种事件
    4. 计时线程:负责计时
    5. 网络线程:负责网络通信

    当上面的线程发生了某些事请,如果该线程发现,这件事情有处理程序,它会将该处理程序加入一个叫做事件队列的内存。当JS引擎发现,执行栈中已经没有了任何内容后,会将事件队列中的第一个函数加入到执行栈中执行。

    JS引擎对事件队列的取出执行方式,以及与宿主环境的配合,称之为事件循环。

    事件队列在不同的宿主环境中有所差异,大部分宿主环境会将事件队列进行细分。在浏览器中,事件队列分为两种:

    • 宏任务(队列):macroTask,计时器结束的回调、事件回调、http回调等等绝大部分异步函数进入宏队列
    • 微任务(队列):microTask,Promise产生的回调进入微队列

    当执行栈清空时,JS引擎首先会将微任务中的所有任务依次执行结束,如果没有微任务,则执行宏任务。

    JS中是否可能有一个函数,执行过程中被其他函数打断?答案是,不可能。

    范例

    	    function A(){
                console.log("A");
                function B(){
                    console.log("B");
                }
                B();
            }
            console.log("global");//全局环境代码!
            A();
            console.log("global over");
    

    打印结果 global A B global over


    全局环境

    函数环境

    执行站 call stack

    首先放---全局环境--创建console

    执行完就删除该环境!!!

    setTimeout(function A(){
        console.log("123");
    }, 3000);
    

    注意:

    1. 执行栈中先放入全局环境,全局环境执行完毕后,才会执行事件队列中的事件,事件队列中又有宏队列和微队列,微队列中的事件执行完毕之后才会执行宏队列。只有promise产生的事件才会放到微队列中,其他都放到宏队列中。

    Promise

    Promise对象表示任务,它用一种标准格式处理异步任务。

    Promise构造函数中传入的函数会被立即执行。

    resolve调用后,把任务标记为成功,可以通过Promise对象的then函数注册处理程序,该程序会在任务标记为成功后执行,该函数的执行是异步的。

    function method() {
                console.log("成哥:monica,能潜规则吗?+5块钱");
                setTimeout(function() {
                    console.log("monica:不行,10块!");
                    setTimeout(function() {
                        console.log("成哥:太贵了!给不起");
                        setTimeout(function() {
                            console.log("邓哥给monica写了一封情书,并附上10块钱");
                            setTimeout(function() {
                                console.log("monica看了情书,十分感动,然后拒绝了他");
                            }, 300)
                        }, 300)
                    }, 300)
                }, 300)
            }
    
            //处理后续任务
            new Promise(function(resolve) {
                console.log("成哥:monica,能潜规则吗?+5块钱");
                setTimeout(function A() {
                    resolve(); //标记事件完成
                }, 300);
            }).then(function B() {
                //会在任务被标记完成之后调用,该函数是异步函数
                return new Promise(function(resolve) {
                    console.log("monica:不行,10块!");
                    setTimeout(function() {
                        resolve();
                    }, 300);
                })
            }).then(function() {
                return new Promise(function(resolve) {
                    console.log("成哥:太贵了!给不起");
                    setTimeout(function() {
                        resolve();
                    }, 300);
                })
            }).then(function() {
                return new Promise(function(resolve) {
                    console.log("邓哥给monica写了一封情书,并附上10块钱");
                    setTimeout(function() {
                        resolve();
                    }, 300);
                })
            }).then(function() {
                console.log("monica看了情书,十分感动,然后拒绝了他");
            })
    

    var prom = new Promise(你要做什么事情);

    promise中的事件会立即执行,执行完成后会用resolve()标记事件完成,.then()函数中的内容,会在上一个promise标记完成后调用 ,注意,.then()函数是异步的,被调用后,是进入事件队列

            var prom = new Promise(function(resolve) {
                console.log("成哥:monica,能潜规则吗?+5块钱");
                setTimeout(function A() {
                    resolve(); //标记事件完成
                }, 300);
            });
            prom.then(function(){
                console.log("B");
            })
            console.log("A");
    

            //处理后续任务
            new Promise(function(resolve) {
                console.log("成哥:monica,能潜规则吗?+5块钱");
                setTimeout(function A() {
                    resolve(); //标记事件完成
                }, 300);
            }).then(function B() {
                //会在任务被标记完成之后调用,该函数是异步函数
                return new Promise(function(resolve) {  //前一个任务执行完马上产生一个新的任务
                    console.log("monica:不行,10块!");
                    setTimeout(function() {
                        resolve();
                    }, 300);
                })
            }).then(function() {
                return new Promise(function(resolve) {
                    console.log("成哥:太贵了!给不起");
                    setTimeout(function() {
                        resolve();
                    }, 300);
                })
            }).then(function() {
                return new Promise(function(resolve) {
                    console.log("邓哥给monica写了一封情书,并附上10块钱");
                    setTimeout(function() {
                        resolve();
                    }, 300);
                })
            }).then(function() {
                console.log("monica看了情书,十分感动,然后拒绝了他");
            })
    

    链式编程!!!

    把回调函数变成了可控制的,且变成了链式的顺序的。

    注意:最容易混淆的是,.then()被调用后,产生的函数事件是异步的,需要进入事件队列(微队列)中,注意,异步的需要进入事件队列中。

            setTimeout(function C() {
                var prom = new Promise(function(resolve) {
                    resolve();
                });
                prom.then(function() {
                    console.log("F");
                })
            }, 0);
            setTimeout(function A() {
                console.log("A");
            }, 0);
    
    
            var prom = new Promise(function(resolve) {
                console.log("B");
                resolve();
                console.log("C");
            });
    
            prom.then(function B() {
                console.log("D");
            });
    
            console.log("E");
    

    打印的顺序是:

    B

    C

    E

    D

    F

    A

    注意:promise里面的事件会立即执行,执行标记完成后,调用.then(),其中的事件会进入微队列等待被执行,定时器等其他异步的事件进入宏队列,等微队列执行完,再执行宏队列中的内容。

    递归

            //1 1 2 3 5 8 13 21
            function getFeibo(n) {
                if (n === 1 || n === 2) {
                    return 1;
                }
                return getFeibo(n - 1) + getFeibo(n - 2);
            }
    
            console.log(getFeibo(3));
    

  • 相关阅读:
    使用C# (.NET Core) 实现模板方法模式 (Template Method Pattern)
    使用C# (.NET Core) 实现单体设计模式 (Singleton Pattern)
    使用C# (.NET Core) 实现抽象工厂设计模式 (Abstract Pattern)
    使用C# (.NET Core) 实现简单工厂(Simple Factory) 和工厂方法设计模式 (Factory Method Pattern)
    使用 dynamic 类型让 ASP.NET Core 实现 HATEOAS 结构的 RESTful API
    使用静态基类方案让 ASP.NET Core 实现遵循 HATEOAS Restful Web API
    .NET Core/.NET之Stream简介
    使用C# (.NET Core) 实现装饰模式 (Decorator Pattern) 并介绍 .NET/Core的Stream
    MySQL 导入数据
    MySQL 导出数据
  • 原文地址:https://www.cnblogs.com/zhizhi0810/p/11099378.html
Copyright © 2011-2022 走看看