Nodejs介绍
- Node.js是一个Javascript运行环境(runtime)。他让Javascript可以开发后端程序,他几乎能实现其他后端语言能实现的所有功能。
- Nodejs是基于Google V8引擎,V8引擎是Google发布的一块开源的Javascript引擎,原来主要用于Chrome浏览器的JS解释部分,但是Ryan Dahl这哥们,鬼才般的,把这个V8引擎搬到了浏览器上,用于做服务器的软件。
为什么要学Nodejs
- Nodejs用户量大:我们无法统计Nodejs软件的下载量,但是我们可以通过Nodejs框架Express的下载量来分析出Nodejs的用户量非常惊人。Nodejs在2017年的时候用户量已经过千万。经过了3年的发展,Nodejs目前的用户量可想而知。
- Nodejs是程序员必备的技能:对于前段开发者而言Nodejs目前是必备的技能,对于其他后端语言开发者而言,会Nodejs找工作也更有优势。
- Nodejs最擅长高并发:Nodejs最擅长的就是处理高并发,在Java、PHP或者.net等服务器端语言中,会为每一个客户端连接创建一个新的线程。而每个线程需要耗费大约2MB内存。也就是说,理论上,一个8GB内存的服务器可以同时连接的最大用户数为4000个左右。要让web应用程序支持更多的用户,就系要增加服务器的数量,而web应用程序的硬件成本当然就要上升了。Nodejs不为每个用户连接常见一个新的线程,而仅仅使用一个线程。当有用户连接了,就触发一个内部事件,通过非阻塞I/O、事件驱动机制,让Node.js程序宏观上也是并行的。使用Nodejs,一个8GB内存的服务器,可以同时处理超过4万用户的连接。
- Nodejs简单:Nodejs语法完全是js语法,只要你懂JS基础就可以学会Nodejs后端开发。是的Nodejs具有开发周期短、开发成本低、学习成本低的优势。
- Nodejs可实现的功能多:Nodejs不仅可以像其他后端语言一样写动态网站、写接口,还可以应用在云计算平台、游戏开发、区块链开发、即时通讯、跨平台App开发、桌面应用开发(electron)、云直播、物联网领域等。
Nodejs环境搭建
Node.js创建第一个应用
- 如果我们使用PHP来编写后端代码时,需要Apache或者Nginx的HTTP服务器,来处理客户端的请求响应,不过对Node.js来说,概念完全不一样了。使用Node.js时,我们不仅仅在实现一个应用,同时还实现了整个HTTP服务器。
// 表示引入http模块
var http = require('http');
/*
request 获取url传过来的信息
response 给浏览器响应信息
*/
http.createServer(function(request, response) {
// 设置响应头
response.writeHead(200, { 'Content-Type': 'text/plain' });
// 表示给页面上面输出一句话并且结束响应
response.end('Hello World');
}).listen(8081); // 端口
console.log('Server running at http://127.0.0.1:8081/');
url模块使用
var http = require('http');
var url = require('url');
http.createServer(function(request, response) {
response.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
response.write("<head> <meta charset='utf-8'> </head>");
console.log(request.url);
if (request.url != '/favicon.ico') {
var userInfo = url.parse(request.url, true).query;
console.log(`姓名:${userInfo.name} -- 年龄:${userI}`);
}
response.end();
}).listen(8081);
supervisor自启动工具
-
supervisor会不停地watch你应用下面的所有文件,发现有文件被修改,就重新载入程序文件这样就实现了部署,修改了程序文件后马上就能看到变更后的结果。不用再重启代码了。
-
首先安装supervisor。
-
npm install supervisor -g //windows sudo npm install supervisor -g //mac
-
-
使用supervisor代替node命令启动应用。
CommonJS
- Javascript是一个强大的面向对象语言,它有很多快速高效的解释器,然而,Javascript标准定义的API为了构建基于浏览器的应用程序。并没有指定一个用于更广泛的应用程序标准库。CommonJS规范的提出了,主要是为了弥补当前Javascript没有标准库的缺陷。它的终极目标就是:提供一个类似Python、Ruby和Java语言的标准库,而不是让Javascript停留在小脚本程序的阶段。用CommonJS API编写出的应用,不仅可以利用Javascript开发客户端应用,而且还可以编写以下应用。
- 服务器端Javascript应用程序。(nodejs)
- 命令行工具。
- 桌面图形界面应用程序。
- CommonJS就是模块化的标准,nodejs就是CommonJS(模块化)的实现。
Nodejs模块化
在Node中,模块分为两类
- 一类是Node提供的模块,称为核心模块;另一类是用于编写的模块,称为文件模块。
- 核心模块部分在Node源代码编译过程中,编译进了二进制执行文件。在Node进程启动时,部分核心模块就被直接加载进内存中,所以这部分核心模块引入时,文件定位和编译执行这两个步骤可以省略掉,并且在路径分析中优先判断,所以它的加载速度是最快的。
- 如:HTTP模块、URL模块、Fs模块都是nodejs内置的核心模块,可以直接引入使用。
- 文件模块则是在运行时动态加载,需要完整的路径分析、文件定位、编译执行过程、速度相比核心模块稍微慢一些,但是用的非常多。这些模块需要我们自定义。接下来我们看一下nodejs中的自定义模块。
CommonJS(Nodejs)中自定义模块的规定:
- 我们可以把公共的功能抽离成一个单独的js文件作为一个模块,默认情况下面这个模块里面的方法或者属性,外面是没法访问的。如果要让外部可以访问里面的方法或者属性,就必须在模块里面通过exports或者moudule.exports暴露属性或者方法。
- 在需要使用这些模块的文件中,通过require的方式引入这个模块。这个时候就可以使用模块里面暴露的属性和方法。
- 如果是对象中的方法,推荐使用
module.exports = xxx;
。 - require时,nodejs默认会找node_modules中对应模块里面的index.js。
- 如果文件名不是index.js也可以通过
npm init --yes
生成package.json文件,package.json中的main代表“入口”。
包与NPM
-
包:Nodejs中除了他自己提供的核心模块外,我们可以自定义模块,也可以使用第三方的模块。Nodejs中第三方模块由包组成,可以通过包来对一组具有相互依赖关系的模块进行统一管理。
-
完全符合CommonJs规范的包目录一般包含如下这些文件。
- package.json:包描述文件。
- bin:用于存放可执行二进制文件的目录。
- lib:用于存放Javascript代码的目录。
- doc:用于存放文档的目录。
-
在Nodejs中通过npm命令来下载第三方的模块(包)。
-
NPM介绍:
- npm是世界上最大的开源代码的生态系统。我们可以通过npm下载各种各样的包,这些源代码(包)我们可以在http://www.npmjs.com找到。
-
npm是随同Nodejs一起安装的包管理工具,能解决Nodejs代码部署上的很多问题,使用场景:
- 允许用户从NPM服务器下载别人编写的第三方包到本地。(silly-datetime)
- 允许用户从NPM服务器下载并安装别人编写的命令行程序(工具)到本地使用。(supervisor)
- 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。
演示使用md5包
- 首先通过命令行找到我们的目录,然后书写
npm init --yes
来导入package.json文件。
- 再自己建立一个空的app.js文件。
- 然后上http://www.npmjs.com找到我们需要的md5包。
- 通过描述,在指定的文件夹下面安装md5的包。
- 之后就可以通过require引入md5使用了。
- 成功的将我们的123456加密了起来。
- 值得注意的是,如果我们之前安装md5的时候不是使用
npm install md5
而是使用npm install md5 --save
我们就可以在package.json文件的dependencies区域发现一段代码:
以后我们要将项目发送给别人就只需要发送下面的文件,不需要发送上面的node_modules文件夹,然后通过一句npm i
就会将项目所需要的依赖一个一个安装上。
NPM命令讲解
npm-v
:查看npm版本。npm install Module Name
:安装模块。npm uninstall Module Name
:卸载模块。npm list
:查看当前目录下已安装的node包。npm info 模块
:查看模块的版本。npm install 模块@指定版本
:安装指定版本的包(非常重要)。
package.json
package.json定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)
- 创建package.json
npm init 或者 npm init --yes
- package.json文件
{
"name": "demo02",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"md5": "^2.3.0",
"silly-datetime": "^0.1.2"
}
"devDependencies": {
}
}
dependencies与devDependencies之间的区别?
- 使用
npm install node_module -save
自动更新 dependencies 字段值; - 使用
npm install node_module -save-dev
自动更新 devDependencies 字段值; - dependencies:配置当前程序所依赖的其他包。
- devDependencies:配置当前程序所依赖的其他包,比如一些工具之类的配置在这里。
^
表示第一位版本号不变,后面两位去最新的。
~
表示前两位不变,最后一个取最新的。
*
表示全部取最新的。
安装淘宝镜像(快)
-
淘宝NPM镜像是一个完整的npmjs.org镜像,你可以用此代替官方版本(只读),同步频率目前为10分钟一次以保证尽量与官方服务同步。
-
我们可以使用我们定制的cnpm(gzip压缩支持)命令行工具代替默认的npm:
npm install -g cnpm --registry=https://registry.npm.taobao.org
(mac系统加sudo添加权限)
-
之后我们就可以通过cnpm替代npm了。
fs模块
/*
1. fs.stat 检测是文件还是目录
2. fs.mkdir 创建目录
3. fs.writeFile 创建写入文件
4. fs.appendFile 追加文件
5. fs.readFile 读取文件
6. fs.readdir 读取目录
7. fs.rename 重命名
8. fs.rmdir 删除目录
9. fs.unlink 删除文件
*/
const fs = require('fs');
// 1. fs.stat 检测是文件还是目录
// fs.stat('./html', function(err, data) {
// if (err) {
// console.log(err);
// return;
// }
// console.log(`是文件:${data.isFile()}`);
// console.log(`是目录:${data.isDirectory()}`);
// });
// 2. fs.mkdir 创建目录
/*
path:将创建的目录路径
mode:目录权限(读写权限),默认777
callback:回调,传递异常参数err
*/
// fs.mkdir('./css', function(err) {
// if (err) {
// console.log(err);
// return;
// }
// console.log('创建成功');
// });
// 3. fs.writeFile 创建写入文件(如果存在会替换文件)
// (path: string | number | Buffer | URL, data: string | Uint8Array | Uint8ClampedArray | Uint16Array | Uint32Array | ... 5 more ... | DataView, callback: NoParamCallback)
// fs.writeFile('./html/index.html', '你好nodejs', (err) => {
// if (err) {
// console.log(err);
// return;
// }
// console.log('创建写入文件成功');
// });
// 4. fs.appendFile 追加文件
// fs.appendFile('./css/base.css', 'bodu{color: red}', (err) => {
// if (err) {
// console.log(err);
// return;
// }
// console.log('appendFile 成功');
// });
// fs.appendFile('./css/base.css', 'h2{color: red}', (err) => {
// if (err) {
// console.log(err);
// return;
// }
// console.log('appendFile 成功');
// });
// 5. fs.readFile 读取文件
// fs.readFile('./html/index.html', (err, data) => {
// if (err) {
// console.log(err);
// return;
// }
// console.log(data);//<Buffer e4 bd a0 e5 a5 bd 6e 6f 64 65 6a 73>
// console.log(data.toString());//你好nodejs
// });
// 6. fs.readdir 读取目录
// fs.readdir('./html', (err, data) => {
// if (err) {
// console.log(err);
// return;
// }
// console.log(data);//[ 'index.html', 'news.html' ]
// });
// 7. fs.rename 重命名 功能:1、重命名 2、移动文件
// fs.rename('./css/aaa.css', './css/index.css', (err) => {
// if (err) {
// console.log(err);
// return;
// }
// console.log('重命名成功');
// });
// fs.rename('./css/index.css', './html/index.css', (err) => {
// if (err) {
// console.log(err);
// return;
// }
// console.log('移动文件成功');
// });
// 8. fs.rmdir 删除目录
// fs.rmdir('./aaa', (err) => {
// if (err) {
// console.log(err);
// return;
// }
// console.log('删除目录成功');
// });
// 9. fs.unlink 删除文件
// fs.unlink('./aaa/index.html', (err) => {
// if (err) {
// console.log(err);
// return;
// }
// console.log("删除文件成功");
// });
这几种方法需要掌握好:
-
fs.stat 检测是文件还是目录
-
fs.mkdir 创建目录(下载mkdirp可创建多级目录)
-
fs.writeFile 创建写入文件
-
fs.appendFile 追加文件
-
fs.readFile 读取文件
-
fs.readdir 读取目录
-
fs.rename 重命名
-
fs.rmdir 删除目录
-
fs.unlink 删除文件
Nodejs新特性async await
es6常见语法
1.let const 模板字符串
2.箭头函数
3.对象、属性的简写
4.模板字符串
5.Promise
/*
1.let const 模板字符串
2.箭头函数
3.对象、属性的简写
4.模板字符串
5.Promise
*/
// 1.let const 模板字符串
// if (true) {
// let a = 123;
// }
// console.log(a);//a is not defined
// 2.箭头函数
// setTimeout(() => {
// console.log('执行');
// }, 1000);
// 3.对象、属性的简写
// var name = 'Aniu';
// var app = {
// name
// }
// console.log(app.name);//Aniu
// var name = 'zhangsan';
// var app = {
// name,
// run() {
// console.log(`${this.name}在跑步`);
// }
// }
// app.run();//zhangsan在跑步
// 4.模板字符串
// var name = '张三';
// var age = 20;
// console.log(`${name}的年龄是${age}`);//张三的年龄是20
// 5.Promise
// 通过回调函数获取异步方法中的数据
// function getData(callBack) {
// setTimeout(function() {
// var name = '张三';
// callBack(name);
// }, 1000);
// }
// getData(function(aaa) {
// console.log(aaa);
// });
// Promise来处理异步 resolve 成功的回调函数 reject失败的回调函数
function getData(resolve, rejest) {
setTimeout(function() {
var name = '张三李四';
resolve(name);
}, 1000);
}
var p = new Promise(getData);
p.then(function(data) {
console.log(data);
});
Async、Await和Promise的使用
- async是“异步”的简写,而await可以认为是async wait的简写。所以应该很好理解async中申明一个异步的function,而await用于等待一个异步方法执行完成。
- 简单理解:
- async是让方法变成异步。
- await是等待异步执行完成。
// 普通方法
// function test() {
// return '您好nodejs';
// }
// console.log(test());
// 异步方法
// async function test() { //Promise { '您好nodejs' }
// return '您好nodejs';
// }
// // console.log(await test());//报错: await必须得用在async的方法里面
// async function main() {
// var data = await test(); //获取异步方法里面的数据
// console.log(data);
// }
// main();//您好nodejs
async function test() {
return new Promise((resolve, reject) => {
setTimeout(function() {
var name = "张三 222";
resolve(name);
}, 1000);
});
}
async function main() {
var data = await test(); //获取异步方法里面的数据
console.log(data);
}
main();
fs从文件流读写数据
以流的方式读取文件
const fs = require('fs');
var readStream = fs.createReadStream('./data/input.txt');
var count = 0;
var str = '';
readStream.on('data', (data) => {
str += data;
count++;
});
readStream.on('end', () => {
console.log(str);
console.log(count);//分多次读取,一点一点读取
});
readStream.on('error', (err) => {
console.log(err);
});
以流的方式写入数据
const fs = require('fs');
var str = '';
for (var i = 0; i < 500; i++) {
str += '今天是七夕节学布谷鸟叫的人也不一定是好人\n';
}
var writeStream = fs.createWriteStream('./data/output.txt');
writeStream.write(str);
// 标记写入完成
writeStream.end();
writeStream.on('finish', () => {
console.log('写入完成');
});
管道流
const fs = require('fs');
var readStream = fs.createReadStream('./kk.png');
var writeStream = fs.createWriteStream('./data/kk.png');
readStream.pipe(writeStream);
适合复制比较大的文件。