初识node (三)
一.async同步异步
铺垫:node是单线程异步的运行代码的
(感觉像同一时间干很多事情,快速的切换上下文)如果想开多线程 ,要开子进程
在node中能用异步,尽量不用同步性能很低
啥是同步?啥是异步?有啥区别?
异步编程是指由于异步I/O等因素,无法同步获得执行结果时,
在回调函数中进行下一步操作的代码编写风格,常见的如setTimeout函数、ajax请求等等。
示例:
for (var i = 1; i <= 3; i++) {
setTimeout(function(){
console.log(i);
}, 0);
};
这里大部分人会认为输出123,或者333。其实它会输出 444
要解决异步问题 就是回调函数,将后续的逻辑当做参数传递给这个函数
异步永远在同步之后执行,如果同步代码执行不能完成,异步永远不会触发
非阻塞(厨师)是异步的前置条件
这里就是我们要说的异步编程了。
高级函数的定义
这里为什么会说到高级函数,因为高级函数是异步编程的基础。
那什么是高级函数呢?
其实高级函数就是把函数作为参数或者是作为返回值。
示例:
function test(v){
return function(){
return v;
}
}
如上就是把一个函数作为一个返回值。
二.箭头函数
啥是箭头函数?
箭头函数是[ES6
]定义函数的新语法
普通函数↓
function a(b,c){
return b+c
}
转换成箭头函数↓
let a=(b,c)=>b+c
[是不是很简洁?]
不只是有外观看起来不一样哦~
1.箭头函数不需要
function声明
2.如果箭头后面是一个{}
需要写return
**3.
this指向
箭头函数中没有this指向,所以this永远指向上一级,从而解决了一部分this指向问题 **示例: let obj = {
a:function () {
setTimeout(()=> {
console.log(this);
});
}
};
obj.a.call(1);这里如果this不改成1,那就是a:function ()
**`但同时也因为this问题在node环境中是无法使用箭头函数的`这个稍后会做详解**
三.global
-node全局对象
因为node在服务端运行所以没有window
这一层作用域
也没有那些window下才有的事件
比如alert,onclick等等,node环境中也没有ajax.
但服务端有global
global上的对象都可以直接访问 ->全局对象global.a={b:12}; console.log(a); 输出{b:12}
如果在node环境console.log(global)会发现下面有很多或熟悉或陌生内置属性,下面着重了解几个典型
1.process
(进程)
-
process 对象是一个 global (全局变量),提供有关信息,
控制当前 Node.js 进程
。作为一个对象,它对于 Node.js 应用程序始终是可用的,故无需使用 require( )来引入。 -
process模块用来
与当前进程互动
,可以通过全局变量process访问
,不必使用require命令加载。它是一个EventEmitter对象的实例
。 -
process对象提供一系列属性,用于返回系统信息.
- process.pid:
当前进程的进程号
。- process.version:
Node的版本,比如v0.10.18
。- process.platform:
当前系统平台,比如Linux
。- process.title:
默认值为“node”,可以自定义该值
。- process.argv:
当前进程的命令行参数数组。
- process.env:
指向当前shell的环境变量,比如process.env.HOME。
- process.execPath:
运行当前进程的可执行文件的绝对路径。
- process.stdout:
指向标准输出。
- process.stdin:
指向标准输入。
- process.stderr:
指向标准错误。
2.Buffer(缓存区)
先简单了解,以后再单独详说
Buffer 类是一个全局变量类型,用来直接处理二进制数据的
。 它能够使用多种方式构建。
-
在 ECMAScript 2015
(ES6)
引入 TypedArray 之前,JavaScript 语言没有读取或操作二进制数据流的机制。Buffer 类
被引入作为Node.js API 的一部分
,使其可以在 TCP 流或文件系统操作等场景中处理二进制数据流
。 -
Buffer 类的实例类似于整数数组,
但 Buffer 的大小是固定的
、且在 V8 堆外分配物理内存。 Buffer 的大小在被创建时确定,且无法调整
。 -
Buffer 类在 Node.js 中是一个
全局变量
,因此无需使用 require('buffer').Buffer。
-
官方例子:
// 创建一个长度为 10、且用 0 填充的 Buffer。
const buf1 = Buffer.alloc(10);
// 创建一个长度为 10、且用 0x1 填充的 Buffer。
const buf2 = Buffer.alloc(10, 1);
// 创建一个长度为 10、且未初始化的 Buffer。
// 这个方法比调用 Buffer.alloc() 更快,
// 但返回的 Buffer 实例可能包含旧数据,
// 因此需要使用 fill() 或 write() 重写。
const buf3 = Buffer.allocUnsafe(10);
// 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
const buf4 = Buffer.from([1, 2, 3]);
// 创建一个包含 UTF-8 字节 [0x74, 0xc3, 0xa9, 0x73, 0x74] 的 Buffer。
const buf5 = Buffer.from('tést');
// 创建一个包含 Latin-1 字节 [0x74, 0xe9, 0x73, 0x74] 的 Buffer。
const buf6 = Buffer.from('tést', 'latin1');
3.console (控制台)
console 模块提供了一个简单的调试控制台
,类似于 Web 浏览器提供的 JavaScript 控制台。
该模块导出了两个特定的组件:
一个 Console 类
,包含 console.log() 、 console.error() 和 console.warn() 等方法,可以被用于写入到任何 Node.js 流。一个全局的 console 实例
,可被用于写入到 process.stdout 和 process.stderr。 全局的 console 使用时无需调用 require('console')。注意:
全局的 console 对象的方法既不总是同步的(如浏览器中类似的 API),也不总是异步的(如其他 Node.js 流)
例子,使用全局的 console:
console.log('你好世界');
// 打印: '你好世界'到 stdout。
console.log('你好%s', '世界');
// 打印: '你好世界'到 stdout。
console.error(new Error('错误信息'));
// 打印: [Error: 错误信息]到 stderr。
const name = '描述';
console.warn(`警告${name}`);
// 打印: '警告描述'到 stderr。
4.立即执行,定时(单次/多次)执行[clearImmediate
]x[setImmediate
]立即启动&[clearInterval
]x[setInterval
]定时循环启动&[clearTimeout
]x[setTimeout
]定时单次启动
Node.js 中的计时器是一种会在一段时间后调用给定的函数的内部构造。 定时器函数何时被调用取决于用来创建定时器的方法以及 Node.js 事件循环正在做的其他工作。定时器都是异步工作的
但如果设置了多个定时器则按照设置定时器的顺序执行
如果设置了三个不同类的定时器在同一时间启动
那么将随机出现三种输出结果
setInterval(function(){
console.log(1)
},0);
setTimeout(function(){
console.log(2)
},0);
setImmediate(function(){
console.log(3)
})
module
(node模块)
Node.js 有一个简单的模块加载系统。 在 Node.js 中,文件和模块是一一对应的(每个文件被视为一个独立的模块)。
当前模块的引用。 具体地说,
module.exports
用于定义一个模块导出什么,且通过 require() 引入。
module
实际上不是一个全局变量,而是每个模块内部的。
在js中通过单利模式和闭包等方法来实现简单的模块化,但是单利模式有缺点:不能保证命名空间不冲突,而且如果命名过于复杂还会导致命名过长的麻烦
此时就通过require(模块)
这种方法来引入外部模块,从而避免上述麻烦(不兼容)
[如何引入外部js文件的模块呢?
]
- 首先要在模块js文件中将模块(函数或变量)
暴露导出
有三种方法: - 第一种:给export增加属性
- 第二种:给module.exports增加属性(引入后可直接调用)
- 第三种不常用 是挂载在global的属性上
例子:
function sum(...arr) {
let total = 0;
arr.forEach(item=>total+=item);
return total;
}
exports.sum = sum; 第一种方法
module.exports.sum = sum; 第二种方法
global.sum = sum; 第三种方法
相对应的三种导出方法也有对应的调用方法
导出后就可以引入了,在引用require方法
let sum=require('./sum') ->括号里写模块的路径
如果用exporas.sum = sum;这种方法
sum.sum(1,2,3)输出时就得这么写
如果使用module.exports.sum 这种方法
那就直接用就行了
sum.(1.2.3.4)
如需安装第三方模块请参考"初识npm
"