淘先锋技术网

首页 1 2 3 4 5 6 7

Node.js

Node.js是一个让JavaScript运行在服务端的开发平台,它的出现使得JavaScript成为与PHP、Python、Perl、Ruby等服务端语言平起平坐!无论是安装前端插件、或是作为脚手架的工具都已成为开发人员必备的技能。Node.js发布于2009年5月,由Ryan Dahl开发实际上是对Chrome V8引擎进行了封装。使得v8在非浏览器运行的更好、运行JavaScript更快~

官方中文文档:http://nodejs.cn/api/

1、初识Node.js

1.1、Node.js简介

1、Node.js是一个能够在服务器端运行JavaScript的开放源代码、跨平台JavaScript运行环境

2、Node采用Google开发的V8引擎运行js代码,使用事件驱动非阻塞异步I/O模型等技术来提高性能,可优化应用程序的传输量和规模。

3、Node大部分基本模块都用JavaScript编写。在Node出现之前,JS通常作为客户端程序设计语言使用,以JS写出的程序常在用户的浏览器上运行。

4、目前,Node已被IBM、Microsoft、Yahoo!、Walmart、Groupon、SAP、 LinkedIn、Rakuten、PayPal、Voxer和GoDaddy等企业采用。

5、核心模块包括文件系统I/O、网络(HTTP、TCP、UDP、DNS、TLS/SSL等)、二进制数据流、加密算法、数据流等等。Node模块的API形式简单,降低了编程的复杂度。
在这里插入图片描述
Node.js的用途:

  • Web服务API,比如REST
  • 实时多人游戏
  • 后端的Web服务,例如跨域、服务器端的请求
  • 基于Web的应用
  • 多客户端的通信,如即时通信

Node.js的历史:

1.2、Node.js之父

每一项技术都有自己的发明者,node.js也不例外,由瑞安·达尔(Ryan Dahl)在2009年5月年发布。Ryan Dahl并非科班出身,在2004年的时候他还在纽约的罗彻斯特大学数学系读博士,直到2006年,也许是厌倦了读博的无聊,他产生了【世界那么大,我想去看看】的念头。于是做出退学的决定,毅然决然的来到了智利的Valparaiso小镇,从那时起他开始学习网站开发,走上了码农的道路~
在这里插入图片描述
Ryan Dahl经过两年的工作后,成为了高性能Web服务器的专家,从接开发应用到变成专门帮客户解决性能问题的专家。期间他开始写一些开源项目帮助客户解决Web服务器的高并发性能问题,他尝试了很多种语言,但是最终都失败了。

在他快绝望的时候,V8引擎来了。V8满足他关于高性能Web服务器的想象。于是在2009年2月它开始着手编写
Node.js

如今nodo.js已有庞大的生态,无论是作为服务端开发(单线程),还是作为插件使用,成为了前端开发必不可少缺少的技术。

1.3、Node.js的安装

下载地址:https://nodejs.org/zh-cn/download/releases/

1、Node.js的安装,在任意命令行窗口使用

// 1.官网下载对应版本安装包
// 2.安装好找的目录下
// 3.配置环境变量,如NODE_PATH=E:\node_js Path=%NODE_PATH%

// 4.node安装比较简单,这里就不详细说明了

2、全局插件的安装,在任意命令窗口中使用

// 1.首先node安装好后,会有如下默认配置:
npm config get prefix
C:\Users\laizhenghua\AppData\Roaming\npm

npm config get cache
C:\Users\laizhenghua\AppData\Roaming\npm-cache

// 2.在当前用户的环境变量path里,会自动增加这么一条C:\Users\Administrator\AppData\Roaming\npm

// 3.隐藏的环境变量 NODE_PATH 值为 C:\Users\Administrator\AppData\Roaming\npm\node_modules

// 4.修改默认配置也就是修改以上信息如:

npm config set prefix npm目录

npm config set cache cache目录

修改环境变量(path + NODE_PATH)

node -v 		// 查看node版本
npm config list	// 查看配置信息
npm config set prefix"D:\dev\nodejs\node_modules\npm\node_gloval_modules"  // 设置全局模块插件存放路径
npm config set cache "D\dev\nodejs\\node_modules\npm\node_cache"		// 设置缓存

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

npm config set registry https://registry.npm.taobao.org 			// 设置默认源

cnpm install express --save			// 安装Express
cnpm install body-parser --save		// node.js中间件,处理JSON,Raw,Text和url编码的数据
cnpm install cookie-parser --save	// 解析Cookie工具,通过req.cookies获取传过来的cookie,并转换成对象
cnpm install multer --save			// node.js中间件,处理enctype="multipart/form-data"的表单数据


https://www.runoob.com/nodejs/nodejs-tutorial.html

node 文件名		// 启动服务

2、Node.js基础-模块化

2.1、COMMONJS规范

说到模块化,程序设计的规模达到了一定程度,则必须对其进行模块化。模块化不仅能降低应用程序的耦合度,还能方便代码复用。这也是COMMONJS规范产生的一个原因:

ECMAScript标准的缺陷:

  • 没有模块系统(ES6已完善)
  • 标准库较少
  • 没有标准接口
  • 缺乏管理系统

模块化:模块化可以有多种形式,但至少应该提供能够将代码分割为多个源文件的机制。在node.js中一个js文件就是一个模块。

服务端系统规模是非常庞大的,不能以现有的JavaScritp模式去管理代码,会导致服务器代码极难维护,所以到了Node.js这个不得不不去解决模块化问题,所以提出了CommonJS规范。CommonJS 的模块功能可以帮我们解决该
问题。

CommonJS规范

  • CommonJS规范的提出,主要是为了弥补当前JavaScript没有模块化标准的缺陷。
  • CommonJS规范为JS指定了一个美好的愿景,希望JS能够在任何地方运行。
  • CommonJS对模块的定义十分简单:
    – 模块引用
    – 模块定义
    – 模块标识

2.2、模块引用

前面我们已经知道,在node.js中一个js文件就是一个模块,那么在其他模块中如何引入呢?

在规范中,定义了require()方法,这个方法接手模块标识,以此将一个模块引入到当前运行环境中。

// 引入其他模块

/*
    1.在node中,通过 require() 函数来引入外部的模块
    2.函数的参数可以是文件的路径,node会根据该路径自动引入外部模块
    3.文件路径如果是相对路径,必须以 ./ 或 ../ 开头
    4.使用require()引入模块以后,该函数会返回一个对象,这个对象代表的是引入的模块
*/
let test = require("./test.js"); // 执行 test.js 里的代码并文件后缀可以省略

// 我们在 test.js 中声明一个变量如:let name = "alex";
console.log(test.name); // undefined
/*
    为何?
    1.在node中,每一个js文件中的js代码都是独立运行在一个函数中,而不是全局作用域
    2.所以一个模块中的变量和函数在其他模块中无法访问
    3.模块需要通过 exports 来向外部暴露变量和方法,其他模块中引入后才能访问,如在test.js中添加 exports.name = "alex";
*/
console.log(test); // { name: 'alex' }

/*
// test.js
exports.add = function (a, b) {
    return a + b;
};
*/
console.log(test.add(1,2)); // 3

2.3、模块标识

我们使用require()引入外部模块时,使用的就是模块标识:

我们可以通过模块标识来找到指定的模块!

模块分成三大类:

/*
核心模块
	- 由node引擎提供的模块
	- 核心模块的标识就是模块的名字
文件模块
	- 由用户自己创建的模块
	- 文件模块的标识就是文件的路径(绝对路径、相对路径)
内建模块
	- 底层由C++编写的内建模块
*/
let fs = require("fs"); // 核心模块
console.log(fs);

扩展:

/*
在node中有一个全局对象 global,它的作用和网页中window类似
    - 在全局中创建的变量都会作为global的属性保存
    - 在全局中创建的函数都会作为global的方法保存
*/
a = 123; // 全局变量
console.log(global.a); // 123

// 如何证明?模块化代码是在函数中执行的?

// Javascript中每个函数都会有一个Arguments对象实例arguments
console.log(arguments); // 有输出就证明代码是在函数中运行的

// 解释
/*
当node在执行模块中的代码时,它会首先在代码的最顶部添加如下代码
function (exports, require, module, _filename, _dirname) {
    ...

    在代码的最底部添加(补全大括号)
}
 */
// 可以输出这个几个参数,你就懂了模块中的代码都是包装在一个函数中执行的

2.4、模块的定义

我们知道exports对象可以导出当前模块的一些变量与函数,并且它是唯一的导出出口。在模块中还存在一个module对象,它代表模块自身,而exports是module的属性。

使用module.exports也可以导出当前模块的变量与方法:

// test.js
exports.name = "alex";
module.exports.age = "21";

// myApp.js
let test = require("./test");

console.log(test.name); // alex
console.log(test.age); // 21

时刻谨记:在Node中一个文件就是一个模块,每个模块具有独立的空间,它们互不干扰,在引用时也显得干净利落。

那么exportsmodule.exports有什么区别呢?

// 他们的关系就好比如下例子
let obj = {};
obj.a = {};

let a = obj.a;
// obj.a 和 a 指向同一个对象
console.log(obj.a === a); // true
a.name = "alex";
console.log(obj.a.name); // alex

// 值得注意的是 exports = module.exports
module.exports = {
	...
}
// module.exports可以导出一个对象,而 exports 不行
// 因为 exports = {} 的时候已经不再指向 module.exports,所以exports只能使用 exports.xxx 的形式导出变量或函数
// 如
module.exports = {
	name: "alex".
	age: 21
}

exports.name = "alex";
exports.age = "21";

2.5、包 package

CommonJS的包规范允许我们将一组相关的模块组合到一起(也可以理解成一组模块的集合),形成一组完整的工具。CommonJS的包规范由包结构包描述文件两个部分组成。

/*
包结构:
	- 用于组织包中的各种文件
	- 包实际上就是一个压缩文件,解压以后还原为目录。符合规范的目录,应该包含如下文件
		- package.json 描述文件
		- bin 可执行二进制文件
		- lib js代码
		- doc 文档
		- test 单元测试
包描述文件:
	- 描述包的相关信息,以供外部读取分析
	- 包描述文件用于表达非代码相关的信息,它是一个JSON格式的文件 – package.json,位于包的根目录下,是包的重要组成部分。

package.json中的字段:
	- name、description、version、keywords
	- maintainers、contributors、bugs
	- licenses、repositories、dependencies
	- homepage、os、cpu、engine、builtin
	- directories、implements、scripts、author
	- bin、main、devDependencies
*/

例如node目录就是一个包:
在这里插入图片描述

3、NPM

NPM(Node Package Manager)是随同Node.js一起安装的包管理工具,能解决Node.js代码部署上的很多问题,常见的使用场景有以下几种:

  • 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
  • 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
  • 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。

对于Node而言:NPM帮助其完成了第三方模块的发布、安装和依赖等。借助NPM,Node与第三方模块之间形成了很好的一个生态系统。

由于新版的Node.js已经集成了npm,所以之前npm也一并安装好了。同样可以通过输入 npm -v来测试是否成功安装。命令如下,出现版本提示表示安装成功:

C:\Users\laizhenghua>npm -v
6.14.5

3.1、npm常用命令

npm -v // 查看版本

npm // 帮助说明

npm search packageName // 搜索模块包

npm init // 初始化一个包
npm init -y // 初始化时跳过提示

npm install 包名 // 在当前目录安装包
npm install 包名 -g // 全局模式安装包
npm install 包名 --save // 安装包并添加到依赖中

npm install 文件路径 // 从本地安装
npm install 包名 -registry=地址 // 从镜像源安装

npm config set registry 地址 // 设置镜像源

npm remove 包名 // 删除一个模块

趁热打铁:任意目录下新建一个文件夹,cmd打开命令行窗口,执行npm init -y,初始化成功后,执行npm install math --save。在根目录下新建index.js,书写如下代码

let math = require("math");
// console.log(math);

console.log(math.sum([1, 2])); // 3

通过npm下载的包都放到node_modules文件夹中,我们通过npm下载的包,直接通过包名引入即可!

node在使用模块名字来引入模块时,它会首先在当前目录的node_modules中寻找是否含有该模块

  • 如果有则直接使用,如果没有则上去一级目录的node_modules中寻找
  • 如果有则直接使用,如果没有则再去上一级目录寻找,直到找到为止
  • 直到找到磁盘的根目录。如果依然没有,则报错

3.2、安装CNPM

默认的镜像源是在国外,在国内下载第三方包的速度极其之慢,也会造成经常下载失败现象。我们可以设置国内的镜像源,加快下载速度如:

淘宝 NPM 镜像地址:https://npm.taobao.org/

安装CNPM:

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

4、文件系统

4.1、Buffer(缓冲区)

操作文件时候,JavaScript数组是不能存储二进制文件的,而buffer就是专门用来存储二进制数据。从结构上看Buffer非常像一个数组,它的元素为16进制的两位数。

实际上一个元素就表示内存中的一个字节。

Buffer中的内存不是通过JavaScript分配的,而是在底层通过C++申请的。也就是我们可以直接通过Buffer来创建内存
中的空间。另外使用buffer不需要引入模块,直接使用即可。

Buffer的使用示例:

// Buffer的使用

let str = "hello world";
let buffer = Buffer.from(str); // 转换成二进制unicode编码

console.log(buffer); // <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
console.log(buffer.length); // 11
console.log(str.length); // 字符串长度

// 在buffer中存储的都是二进制数据,但是在显示时都是以16进制的形式显示,buffer中每一个元素的范围是从00 - ff,即一个元素占一个字节

// 创建一个指定大小的buffer,注意Buffer构造函数大多是都弃用了,不推荐使用
let buf = new Buffer(1024); // 1042个字节
console.log(buf.length); // 1024

// 创建指定大小Buffer推荐使用Buffer.alloc()/Buffer.allocUnsafe()等方法。更多内容可查看官方文档
let buffer2 = Buffer.alloc(10);
console.log(buffer2.length); // 注意buffer的大小一旦确定,则不能修改,Buffer实际上是对底层内存直接操作
// 通过索引操作元素
buffer2[0] = 0;
buffer2[1] = 255;
console.log(buffer2[1]); // 255

更多内容请参照官方文档:http://nodejs.cn/api/buffer.html

4.2、fs文件系统

fs(File System):在Node中,与文件系统的交互是非常重要的,服务器的本质就将本地的文件发送给远程的客户端。Node通过fs模块来和文件系统进行交互,该模块提供了一些标准文件访问API来打开、读取、写入文件,以及与其交互。

// 要使用fs模块,首先需要对其进行加载
let fs = require("fs");

同步和异步调用:

/*
- fs模块中所有的操作都有两种形式可供选择 同步 和 异步。
- 同步文件系统会 阻塞程序 的执行,也就是除非操作完毕,否则不会向下执行代码。
- 异步文件系统不会阻塞程序的执行,而是在操作完成时,通过回调函数将结果返回。
*/

官方文档:http://nodejs.cn/api/fs.html

文件的基本操作: