作用域、事件、异步

2019-06-05  本文已影响0人  致自己_cb38

作用域、事件、异步

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

上一篇 下一篇

猜你喜欢

热点阅读