作用域、事件、异步
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.pngimage.png
示例:使用fs读取文件流,监听data事件
7. 异步与同步(重点)
7.1. 基本概念
同步:一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的。
异步:每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。
案例分析:
张三去火车票代售窗口买票,现在该张三购票了,张三后面是李四,他也等着买票。
1、张三:买一张明天到大理的火车票
售票MM:对不起,明天到大理的火车票已经没有了
张三:啊!居然没有了,你等我一下,我打电话问问我女朋友,改买多久的票。 (此时,售票员什么事情都做不了,只得等我打完电话,而张三背后的李四变得非常的焦躁,心中:“我靠,耽误我时间,浪费我青春,你难道就不知道去一边打电话吗?等我买了票,你差不多也打完了。”)
30秒过去了.....
张三:美女,那就换一张后天到大理的火车票吧。
售票MM:好的,给你。
李四:买一张去源码时代的火车票,我要去学Web前端.
....
2、张三:买一张明天到大理的火车票
售票MM:对不起,明天到大理的火车票已经没有了
张三:好吧,那我先打电话问问我女朋友,问好后,我在跟你说。(一个小的举动,从售票窗口让开)
李四:买一张去源码时代的火车票,我要去学Web前端.
售票MM:好的,给你。
.....
张三电话打完了
张三:美女,那就换一张后天到大理的火车票吧。
售票MM:好的,给你。
1、同步:总是等待上一个任务完成后,才开始下一个任务的执行。
image.png2、异步:开始一个(异步)任务,任务去执行,但是不会让后面的任务等待(阻塞),后面的任务继续执行,(异步)任务执行完毕后,会进行通知(回调)。
image.png7.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. 重点
-
作用域
-
事件编程
-
异步与同步
8.2. 难点
- 异步与同步
8.3. 如何掌握?
-
通过执行代码验证原理。
-
将常见的用法截图保存到文件夹中,时常回顾。
8.4. 排错技巧(技巧)
- console.log()方法。
9. 作业
作业难度: ☆☆
1、NodeJs的作用域有哪些
2、回调函数作用
3、编写上课异步编程前两种方式代码
10. 面试题
-
异步和同步有什么区别?
-
JavaScript的异步编程是如何实现的?
11. 扩展知识或课外阅读推荐(可选)
11.1. 扩展知识
11.2. 课外阅读
Event Loop: http://www.ruanyifeng.com/blog/2014/10/event-loop.html
网友评论