美文网首页
作用域、事件、异步

作用域、事件、异步

作者: 致自己_cb38 | 来源:发表于2019-06-05 16:25 被阅读0次

    作用域、事件、异步

    1. 课程介绍

    Ø CNPM(淘宝NPM)

    Ø NodeJS控制台

    Ø NodeJS作用域(掌握)

    Ø NodeJS事件编程(了解)

    Ø NodeJS异步(掌握)

    2. CNPM

    在我们中国,要下载 npm 包非常慢,如果使用 cnpm 下载包就非常快了。

    CNPM是taobao提供的一个完整 npmjs.org 镜像,cnpm与npm的内容每10分钟会同步一次。

    安装cnpm:

    npm install -g cnpm --registry=https://registry.npm.taobao.org
    

    使用cnpm:

    cnpm install <模块名>
    

    3. NodeJS控制台

    console 模块提供了一个简单的调试控制台,类似于 Web 浏览器提供的 JavaScript 控制台。不过Node中的控制台输出至CMD窗口。Node.js中,可以通过console对象的各种方法向控制台中输出内容。

    //普通输出
    console.log("hello itsource");
    //错误输出
    console.error("错误消息");
    //time(flag) 与 timeEnd(flag) 统计一段代码的执行时间,注意time、timeEnd的flag需一致
    console.time("t1");
    for(var i=0;i<1000;i++){
        console.log("hehe");
    }
    console.timeEnd("t1");
    
    //assert(表达式,"文本消息") 断言:表达式如果为真
    console.assert(3>10,"断言失败,条件不成立");
    

    4. NodeJS作用域

    4.1. 什么是作用域

    作用域:规定了一个变量和函数可使用的范围,作用域分为两种:全局作用域、局部作用域(函数作用域)

    4.2. NodeJS作用域

    NodeJs中一个文件就是一个模块,模块中使用var定义的变量为局部作用域,只能在该模块中使用,因为模块在使用时会把NodeJs编译为一个函数,那么使用var的定义的变量,理所当然的只能在这个模块(函数)中使用。

    比如:某模块我们编写了以下代码

    var a = 10;
    

    NodeJs会在执行之前,编译这个模块为:

    function (exports, require, module, __filename, __dirname) { 
            var a = 10;// a为局部变量      
    }
    
    image.png
    注意:
    一个node文件就是一个模块

    模块的内部是写在一个函数里面的,这个函数是隐形的.可以使用上面的代码打印出这个函数

    模块内部其实写的就是函数的函数体.函数数体属于局部空间,所以内部的变量与函数外部是不可见的

    由于外部想要使用内部的一些函数或者变量,就需要函数导出一些内容.

    提供了一个参数exports 对象,js的对象传递都是引用传递.

    require 在模块的内部也有可能是用到其他的模块,所以需要一个办法引入其他模块. require是一个函数

    module 里面是当前模块一些信息,module是一个对象

    __filename 与 __dirname 魔术常量.根据当前的模块的不同发生变化.

    4.3. NodeJS全局作用域和全局对象

    NodeJs定义一个变量,如果是不使用var,而直接给变量赋值,那么就是一个全局变量,一个全局变量可以被其他模块所使用。

    username = “123123”;
    

    NodeJs中的全局对象为global,所以通过给这个对象上面添加属性,也是全局变量。

    global.address = “成都源码时代”;
    

    注意:尽量少使用全局变量,避免变量冲突。

    5. NodeJS回调函数

    5.1. 回调函数

    回调函数,或简称回调(Callback),是指通过函数参数传递到其它代码的,某一块可执行代码的引用。

    实现机制:

    ⑴定义一个回调函数;(非常普通的函数)

    ⑵将回调函数的函数引用地址作为参数传递给调用者(调用者本身也是一个函数);

    ⑶当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。

    //cb回调函数
    function cb(){
      console.log(“hello”);
    }
    
    //setTimeout让传入进来的cb延迟1秒后运行。
    setTimeout(cb,1000);
    

    5.2. 如何使用回调函数

    传递函数名

    function fn(){
        console.log("这是一个回调函数!")
    }
    global.setTimeout(fn,1000);
    

    传入一个匿名函数

    global.setTimeout(function fn(){
        console.log("这是一个回调函数!")
    },1000);
    

    5.3. 回调函数的用途

    回调函数在JavaScript非常常用,最简单的就是事件注册,或异步函数

    当某个事件发生或者某个任务完成时,需要做一些事情,那么我们就会用到回调函数。

    比如jQuery中:

      $("#mydiv").click(function(){//事件回调函数
            
         });
    

    比如动画:

      function animate(arg1,arg2....,callback){
          var timer = setInterval(function(){
             if(!flag){//判断动画是否应该停止
                clearInterval(timer);
                callback(); //回调函数
             }
           },30);
      }
      animate(x,y,z,function(){
     //回调函数
      });
    

    6. NodeJS事件编程(了解)

    之前编写过客户端JavaScript脚本代码,你肯定对事件有了相当程度的了解。对页面进行交互操作时,每个元素都可能会触发一个事件,例如当用户单击一个按钮时,就会触发按钮的click事件。

    客户端事件分三大类:

    鼠标;

    键盘;

    对象状态;(ajax)

    6.1. events事件模块

    在Node.js中,许多对象也将触发各种事件,NodeJs有events模块就是提供事件编程的api,所有具有触发事件的对象都继承或内部包含了EventEmitter对象。

    //events模块中的EventEmitter对象,定义了事件对象的基础信息和行为。
    var EventEmitter = require("events").EventEmitter;
    //创建一个事件对象
    var event = new EventEmitter();
    //注册事件 , "myevent"是事件名。
    event.on("myevent",function(name){
        console.log(name+":hello");
    });
    //触发事件. "myevent"触发事件的名称,"二狗"触发事件的参数。
    event.emit("myevent","二狗");
    

    6.2. EventEmitter事件对象

    image.png
    image.png

    示例:使用fs读取文件流,监听data事件

    7. 异步与同步(重点)

    7.1. 基本概念

    同步:一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的。

    异步:每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。

    案例分析:

    张三去火车票代售窗口买票,现在该张三购票了,张三后面是李四,他也等着买票。

    1、张三:买一张明天到大理的火车票

    售票MM:对不起,明天到大理的火车票已经没有了

    张三:啊!居然没有了,你等我一下,我打电话问问我女朋友,改买多久的票。 (此时,售票员什么事情都做不了,只得等我打完电话,而张三背后的李四变得非常的焦躁,心中:“我靠,耽误我时间,浪费我青春,你难道就不知道去一边打电话吗?等我买了票,你差不多也打完了。”)

    30秒过去了.....

    张三:美女,那就换一张后天到大理的火车票吧。

    售票MM:好的,给你。

    李四:买一张去源码时代的火车票,我要去学Web前端.

    ....

    2、张三:买一张明天到大理的火车票

    售票MM:对不起,明天到大理的火车票已经没有了

    张三:好吧,那我先打电话问问我女朋友,问好后,我在跟你说。(一个小的举动,从售票窗口让开)

    李四:买一张去源码时代的火车票,我要去学Web前端.

    售票MM:好的,给你。

    .....

    张三电话打完了

    张三:美女,那就换一张后天到大理的火车票吧。

    售票MM:好的,给你。

    1、同步:总是等待上一个任务完成后,才开始下一个任务的执行。

    image.png

    2、异步:开始一个(异步)任务,任务去执行,但是不会让后面的任务等待(阻塞),后面的任务继续执行,(异步)任务执行完毕后,会进行通知(回调)。

    image.png

    7.2. 异步编程实现

    NodeJS中共有三种编程方式:

    2、回调函数

    3、事件(基于回调)

    4、Promise(ES6)

    7.2.1. 回调函数

    setTimeout(callback,ms); //延迟ms毫秒后,执行callback函数,延迟的过程,不会影响后面代码的执行。
    
    setTimeout(function(){
      console.log(“1”);
    },1000);
    console.log(“2”);
    
    var s = 13;
    setTimeout(function(){
       s = 31;
    },1000); 
    console.log(s);
    

    7.2.2. 事件

    //fs:文件系统模块,提供对文件的操作
    var fs = require("fs");
    //创建输出流,读取文件
    var stream = fs.createReadStream("./1.jpg");
    //读取数据事件,每次读取都会触发。
    stream.on("data",function(data){
        console.log(data);
    });
    //读取数据完毕
    stream.on("end",function(){
        console.log("文件读取完毕");
    });
    console.log(‘代码执行到了’);
    

    7.2.3. Promise

    Promise(承诺)就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。

    Promise 对象有以下两个特点:

    (1)对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和 Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。

    (2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

    Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 方法和 reject 方法。

    如果异步操作成功,则用 resolve 方法将 Promise 对象的状态,从「未完成」变为「成功」(即从 pending 变为 resolved);

    如果异步操作失败,则用 reject 方法将 Promise 对象的状态,从「未完成」变为「失败」(即从 pending 变为 rejected)。

    var promise = new Promise(function(resolve, reject) {
     if (/* 异步操作成功 */){
     resolve(value);
     } else {
     reject(error);
     }
    });
    
    promise.then(function(value) {
     // success
    }, function(value) {
     // failure
    });
    

    8. 课程总结

    8.1. 重点

    1. 作用域

    2. 事件编程

    3. 异步与同步

    8.2. 难点

    1. 异步与同步

    8.3. 如何掌握?

    1. 通过执行代码验证原理。

    2. 将常见的用法截图保存到文件夹中,时常回顾。

    8.4. 排错技巧(技巧)

    1. console.log()方法。

    9. 作业

    作业难度: ☆☆

    1、NodeJs的作用域有哪些

    2、回调函数作用

    3、编写上课异步编程前两种方式代码

    10. 面试题

    1. 异步和同步有什么区别?

    2. JavaScript的异步编程是如何实现的?

    11. 扩展知识或课外阅读推荐(可选)

    11.1. 扩展知识

    11.2. 课外阅读

    Event Loop: http://www.ruanyifeng.com/blog/2014/10/event-loop.html

    相关文章

      网友评论

          本文标题:作用域、事件、异步

          本文链接:https://www.haomeiwen.com/subject/qqurxctx.html