一、 第三方模块 Gulp
基于node平台开发的前端构建工具。
将机械化操作编写成任务,想要执行机械化操作时执行一个命令行命令任务就能自动执行了。
用机器代替手工,提高开发效率。
二、 Gulp 能做什么
- 项目上线,HTML、CSS、JS文件压缩合并
- 语法转换(es6、less…)
- 公共文件抽离
- 修改文件浏览器自动刷新
三、Gulp使用
1.使用npm install gulp 下载gulp库文件
2.在项目根目录下简历gulpfile.js文件
3.重构项目的文件夹结构 src目录放置源代码文件 dist目录放置构建后文件
4.在gulpfile.js文件中编写任务
5.在命令行工具中执行gulp任务
四、 Gulp中提供的方法
- gulp.task(): 创建gulp任务
- gulp.src(): 获取任务要处理的文件
- gulp.dest(): 输出文件
- gulp.watch(): 监控文件的变化
//1.引用gulp模块
const gulp = require('gulp');
//2.gulp.task() 创建任务
//两个参数 第一个参数:任务名字, 第二个参数:回调函数
gulp.task('first', () => {
console.log('我们人生中的第一个gulp任务执行了');
//3.使用gulp.src()获取要处理的文件
gulp.src('./src/css/base.css');
//4.我们要将gulp.dest()处理输出文件代码写在.pipe()方法里,即使在dist目录下没有css文件,执行代码时会自动创建
.pipe(gulp.dest('dist/css'));
})
怎样去运行上面的代码呢,在安装gulp库文件的基础上,我们再运行npm install gulp-cli -g 命令行代码,然后使用gulp 任务名称 命令行代码取运行,在上面这个例子,就是运行gulp first
五、Gulp插件
参考网站: https://www.npmjs.com/package/gulp
-
gulp-htmlmin: html文件压缩
-
gulp-csso: 压缩css
-
gulp-babel: JavaScript语法转换
-
gulp-less: less语法转换
-
gulp-uglify: 压缩混淆JavaScript
-
gulp-file-include: 公共文件包含
-
browsersync: 浏览器实时同步
插件的使用: 1.先安装 npm install 插件名称 2.在已引入gulp模块的基础上引入插件模块 3.再在处理文件代码块.pipe()里面调用相应的方法
5.1 html任务 (gulp-htmlmin、gulp-file-include)
- html文件中代码的压缩操作
- 抽取HTML文件中的公共代码
3.注意的是: 先抽取公共部分,再压缩
const gulp = require('gulp');
const htmlmin = require('gulp-htmlmin');
const fileinclude = require('gulp-file-include');
gulp.task('htmlmin', () => {
gulp.src('./src/*.html');
//抽取html公共部分
.pipe(fileinclude());
//压缩html文件中的代码
.pipe(htmlmin({ collapsewhitespace: true }));
.pipe(gulp.dist('dist'));
})
补充:在利用gulp插件抽取html公共部分之前,我们自己先去抽取公共html代码。例如a.html和b.html有相同的头部html代码,我们就可以将这部分代码封装到一个common的head.html文件中,然后在a页面和b页面之前写头部html代码的地方,利用@@include(’./commom/head.html’)引入头部代码即可
5.2 css任务(gulp-less、gulp-csso)
- less语法的转化
- css的压缩
const gule = require('gulp');
const less = require('gulp-less');
const csso = require('gulp-csso');
gulp.task('cssmin', () => {
//选择css目录下的所有less文件以及css文件
gulp.src(['./src/css/*.less', './src/css/*.css']);
//将less语法转换为css语法
.pipe(less());
//将css代码进行压缩
.pipe(csso());
//将处理结果进行输出
.pipe(gulp.dest('dist/css'))
})
5.3 js任务(gulp-babel、gulp-uglify)
1.es6语法转换
2.js代码压缩
const gulp = require('gulp');
const babel = require('gulp-babel');
const uplify = require('hulp-uglify');
gulp.task('jsmin', () => {
gulp.src('./src/*.js');
.pipe(babel({
//它可以判断当前代码运行环境,将代码转换为当前运行环境所支持的代码
presets: ['babel/env']
}));
.pipe(uglify());
.pipe(gulp.dest(dist/js));
})
5.4 复制文件夹
const gulp = require('gulp');
gulp.task('copy', () => {
gulp.src('./src/images/*');
.pipe(gulp.dest('dist/images'));
gulp.src('./src/lib/*');
.pipe(gulp.dest('dist/lib'));
})
5.5 构建任务
gulp.task('default', ['htmlmin', 'cssmin', 'jsmin', 'copy']);
只要在命令行工具中运行gulp default或gulp 命令,就会执行数组中所有的命令;
六、package.json文件
6.1 node_modules文件夹的问题
里面的文件夹很多,如果传输会造成传输速度过慢和文件冗余的问题,因此我们传输的时候不会传输,那怎样解决这个问题呢?看下面
6.2 package.json文件的作用
- 项目描述文件。记录了当前项目信息,例如项目名称、版本、作者、GitHub地址、当前项目依赖了哪些第三方模块等。
- 使用 npm install -y命令生成文件。-y 就是yes的意思,使用默认。
- 别人拿到项目的时候,会使用npm i 命令,根据package.json里面dependencies依赖项依次自动下载所依赖的模块,这样就不必传输node_modules文件了。
- package.json文件夹中有个script字段,可设置别名。
"scripts" : [ "build" : "nodemn app.js" ]
在命令行中只要输入 npm run build,就会执行nodemon app.js这个命令。
6.3 项目依赖 和 开发依赖
项目依赖
-
在项目的开发阶段和线上运营阶段,都需要以来的第三方包,称为项目依赖。
-
使用npm install 包名 命令下载的文件会默认被添加到package.json文件的dependencies字段中
开发依赖 -
在项目的开发阶段需要依赖,线上运营阶段不需要依赖的第三方包,称为开发依赖
-
使用npm run 包名 --save-dev 命令将包添加到package.json文件的devDependencies字段中
注意: 1.使用npm install, 会下载所有依赖,包括开发依赖和项目依赖。 2.使用npm install --production, 会下载项目依赖
6.4 package-lock.json文件的作用
记录了模块与模块之间的依赖关系,还有版本,下载地址等。
好处:
1.锁定包的版本,确保再次下载时不会因为包版本不同而产生问题
2.加快下载速度。因为改文件中已经记录了包的下载地址和项目所依赖第三方包的树状结构,重新安装时只需下载即可,不需要做额外的工作。
七、Node.js模块的加载机制
7.1 模块查找规则 – 当模块拥有路径但没有后缀时
require('./find.js');
require('./find');
- require方法根据模块路径查找模块,如果是完整路径,直接引入模块,如上第一行代码。
- 如果模块后缀省略,先找同名js文件,如果没有,再找同名文件夹
- 如果存在同名文件夹,找文件夹中的index.js
- 如果同名文件夹中没有index.js,就去找同名文件夹中package.json文件中查找main选项中的入口文件
- 如果找指定的入口文件不存在或者没有指定的入口文件就会报错,模块没有被找到。
7.2 模块查找规则 – 模块没有路径也没有后缀时
require('find')
- Node.js会假设他是系统模块
- node.js回去node_modules文件夹中
- 首先查看是否有该名字的js文件
- 如果没有,则查找是否有同名的文件夹
- 如果有同名文件夹,则看同名文件中是否有index.js
- 如果没有,则看同名文件夹下的package.json中的main选项确定入口文件
- 如果入口文件不存在或没有指定的入口文件,就会报错。
八、服务器端基础概念
8.1 网站的组成
客户端:在浏览器中运行的部分,就是用户看到并与之交互的界面程序,使用HTML、css、JavaScript构建。
服务器:在服务器中运行的部分,负责存储数据和处理应用逻辑。
8.2 Node 网站服务器
能够提供网站访问服务的机器就是网站服务器,它能够接受客户端的请求,能够对请求做出响应。
8.3 IP地址
互联网中设备的唯一标识。Internet Protocol Address的缩写,互联网协议地址
8.4 域名
IP地址难以记忆,就产生了域名的概念,所谓域名就是平时上网所使用的网址。
8.5 端口
端口是计算机与外界通讯交流的出口,用来区分服务器电脑中提供的不同服务。
8.6 URL
统一资源定位符。是专为标识Internet网上资源位置而设的一种编址方式。
组成:
传输协议://服务器IP或域名:端口/资源所在位置标示
https://www.cnblogs.com/joe235/p/12745332.html
http: 超文本传输协议。提供 了一种发布和接收html页面的方法
https:是以安全为目的HTTP通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性。
8.7 开发过程中客户端和服务器端的说明
本机域名: localhost
本机IP:127.0.0.1
九、创建web服务器
// 用于创建网站服务器的系统模块http
const http = require('http');
// app 就是创建的网站服务器对象
const app = http.createServer();
// 当客户端发送请求的时候,第一个参数 请求名称,第二个参数 回调函数 request 和 resolve, 响应数据放在res.end()中
app.on('request', (req, res) => {
// 响应
res.end('<h1>hello, user</h1>')
});
//监听端口
app.listen(3000);
consosle.log('网站服务器启动了');
十、Http协议
10.1 Http协议的概念
超文本传输协议,规定了如何从网站服务器传输超文本到本地浏览器。它基于客户端服务器架构工作,是客户端(用户)和服务器(网站)请求和应答的标准。
10.2 报文
在http请求和响应的过程中传递的数据块就报文,包括要传送的数据和一些附加信息,并且要遵循规定好的格式
10.3 请求报文
1.请求方式(可用req.method获取)
- Get 请求数据
- Post 发送数据
// 用于创建网站服务器的系统模块http
const http = require('http');
// app 就是创建的网站服务器对象
const app = http.createServer();
// 当客户端发送请求的时候,第一个参数 请求名称,第二个参数 回调函数 request 和 resolve, 响应数据放在res.end()中
app.on('request', (req, res) => {
//获取请求方式
// req.method
console.log(req.method);
// 响应
res.end('<h1>hello, user</h1>')
});
//监听端口
app.listen(3000);
console.log('网站服务器启动了');
2.请求地址(可用req.url获取)
// 用于创建网站服务器的系统模块http
const http = require('http');
// app 就是创建的网站服务器对象
const app = http.createServer();
// 当客户端发送请求的时候,第一个参数 请求名称,第二个参数 回调函数 request 和 resolve, 响应数据放在res.end()中
app.on('request', (req, res) => {
//获取请求方式
// req.method
// console.log(req.method);
// if (req.method == 'POST') {
// res.end('post');
// } else if (req.method == 'GET') {
// res.end('get');
// }
// 获取请求地址
// req.url
// console.log(req.url);
// 根据请求地址界面显示不同内容
if (req.url == '/index') {
res.end('welcome homepage');
} else if (req.url == '/list') {
res.end('welcome listpage');
} else {
res.end('not found');
}
// 响应
res.end('<h1>hello, user</h1>')
});
//监听端口
app.listen(3000);
console.log('网站服务器启动了');
3.请求报文信息(可用req.headers获取)
// 用于创建网站服务器的系统模块http
const http = require('http');
// app 就是创建的网站服务器对象
const app = http.createServer();
// 当客户端发送请求的时候,第一个参数 请求名称,第二个参数 回调函数 request 和 resolve, 响应数据放在res.end()中
app.on('request', (req, res) => {
//获取请求方式
// req.method
// console.log(req.method);
// if (req.method == 'POST') {
// res.end('post');
// } else if (req.method == 'GET') {
// res.end('get');
// }
// 获取请求地址
// req.url
// console.log(req.url);
// 根据请求地址界面显示不同内容
// if (req.url == '/index') {
// res.end('welcome homepage');
// } else if (req.url == '/list') {
// res.end('welcome listpage');
// } else {
// res.end('not found');
// }
// 请求报文信息
// req.headers
console.log(req.headers);
// 响应
res.end('<h1>hello, user</h1>')
});
//监听端口
app.listen(3000);
console.log('网站服务器启动了');
在命令行中显示结果:
如果只想获取accept:选项的信息,那么可以写为
console.log(req.headers['accept:']);
10.5 响应报文
1、HTTP状态码
- 200 请求成功
- 404 请求的资源没有被找到
- 500 服务器错误
- 400 客户端请求有语法错误
比如例子:
res.writeHead(200);
res.writeHead(404);
2、内容类型:
- text/html
- text/css
- application/javascript
- image/jpeg
- app;ication/json
例如添加纯文本类型:
res.writeHead(200, {
'content-type': 'text/plain'
})
例如添加html并设置utf8,防止输出内容为中文时出现乱码:
res.writeHead(200, {
'content-type': 'text/html;charset= utf8'
})
十一、 http请求与相应处理
11.1 请求参数
客户端向服务端发送请求时,有时候需要携带一些客户信息,客户信息需要通过请求参数的形式传递到服务器,比如登陆操作。
11.2 GET 请求参数
参数被放置在浏览器地址中,例如:http://localhost:3000/index?name=zhangsan&age=20
node 内置的 url 模块,用于处理 url 地址
//用于处理url地址
const url = require('url');
url.parse(req.url);//返回对象
在浏览器中"http://localhost:3000/index?name=zhangsan&age=20"
修改app.js文件:
// 用于创建网站服务器的系统模块http
const http = require('http');
// 用于处理 url 地址
const url = require('url');
// app 就是创建的网站服务器对象
const app = http.createServer();
// 当客户端发送请求的时候,第一个参数 请求名称,第二个参数 回调函数 request 和 resolve, 响应数据放在res.end()中
app.on('request', (req, res) => {
//获取请求方式
// req.method
// console.log(req.method);
// if (req.method == 'POST') {
// res.end('post');
// } else if (req.method == 'GET') {
// res.end('get');
// }
//设置请求状态码
// res.writeHead(400);
// 设置请求内容类型
res.writeHead(200, {
// 设置纯文本
// 'content-type': 'text/plain'
//设置html,防止出现乱码utf8
'content-type': 'text/html; charset=utf8'
})
// console.log(req.url);
// console.log(url.parse(req.url));
// 第一个参数:要解析的url地址
// 第二个参数:将查询参数解析为对象的形式
// console.log(url.parse(req.url, true));
// let params = url.parse(req.url, true).query;
// console.log(params.name);
// console.log(params.age);
let { query, pathname } = url.parse(req.url, true);
console.log(query.name);
console.log(query.age);
// 获取请求地址
// req.url
// console.log(req.url);
// 根据请求地址界面显示不同内容
if (pathname == '/index' || pathname == '/') {
res.end('<h1>欢迎来到首页</h1>');
} else if (pathname == '/list') {
res.end('welcome to listpage');
} else {
res.end('not found');
}
// 请求报文信息
// req.headers
// console.log(req.headers);
// 响应
res.end('<h1>hello, user</h1>')
});
//监听端口
app.listen(3000);
console.log('网站服务器启动了');
11.3 POST 请求参数
- 参数被放在请求体中(报文)进行传输
- 获取POST参数炫耀使用data事件和end事件
- 使用queryString系统模块将参数转换为对象格式
在一个form.html如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- method 指定当前表单提交的方式 -->
<!-- action 指定当前表单提交的地址 -->
<form method="post" action="http://localhost:3000">
<input type="text" name="username" />
<input type="password" name="password" />
<input type="submit" value="提交" />
</form>
</body>
</html>
在post.js如下:
// 用于创建网站服务器的系统模块http
const http = require('http');
//导入系统模块 querystring 用于将http参数转换为对象格式
const querystring = require('querystring');
// app 就是创建的网站服务器对象
const app = http.createServer();
// 当客户端发送请求的时候,第一个参数 请求名称,第二个参数 回调函数 request 和 resolve, 响应数据放在res.end()中
app.on('request', (req, res) => {
//post参数是通过事件的方式接受的
// data 当请求参数传递的时候触发data事件
// end 当参数传递完成的时候触发end事件
let paramsString = '';
req.on('data', params => {
paramsString += params;
})
req.on('end', () => {
console.log(querystring.parse(paramsString));
})
// 响应
res.end('ok')
});
//监听端口
app.listen(3000);
console.log('网站服务器启动了');
在命令窗口中会出现:
11.4 路由
路由是指客户端请求地址与服务器端程序代码的对应关系。简单来说,就是请求什么相应什么。
例子:新建route文件夹,新建app.js文件:
// 1. 引入系统模块 http
// 2. 创建web网站服务器
// 3. 为网站服务器添加请求事件
// 4. 实现路由功能
// 4.1 获取请求方式
// 4.2 获取请求地址
const http = require('http');
const url = require('url');
const
const app = http.createServer();
app.on('request', (req, res) => {
// 获取请求方式 req.methd 小写
let method = req.method.toLowerCase();
// 获取请求地址
let { query, pathname } = url.parse(req.url);
res.writeHead(200, {
'content-type': 'text/html;charset=utf8'
});
if (method == 'get') {
if (pathname == '/' || pathname == '/index') {
res.end('欢迎来到首页');
} else if (pathname == '/list') {
res.end('欢迎来到列表页');
} else {
res.end('您访问的页面不存在');
}
} else if (method == 'post') {
}
})
app.listen(3000);
console.log('web服务器成功启动');
11.5 静态资源
服务器不需要处理,可以直接响应给客户端的资源就是静态资源,例如css、JavaScript、image文件。
新建static文件夹,并创建public文件夹,创建default.html:
<h1>例如展示页面</h1>
在static文件夹下新建app.js文件;
const http = require('http');
const url = require('url');
const path = require('path');
const fs = require('fs');
// 第三方模块mime 可以根据当前的请求路径分析出这个资源的类型,然后将资源的类型全部返回给你
const mime = require('mime');
const app = http.createServer();
app.on('request', (req, res) => {
// 获取请求路径
let pathname = url.parse(req.url).pathname;
pathname = pathname == '/' ? '/default.html' : pathname;
// 将用户的请求路径转换为实际的服务器硬盘路径
let realPath = path.join(__dirname, 'public' + pathname);
let type = mime.getType(realPath);
console.log(type);
// 读取文件
fs.readFile(realPath, (error, resolve) => {
if (error != null) {
res.writeHead(404, {
'content-type': 'text/html;charset=utf8'
});
res.end('文件读取失败');
return;
}
res.writeHead(200, {
'content-type': type + ';charset=utf8'
})
res.end(resolve);
})
})
app.listen(3000);
console.log('web服务器成功启动');
这里需要用到一个第三方模块:mime
功能是:可以根据当前的请求路径分析出这个资源的类型,然后把资源的类型通过返回值返给你。
11.6 动态资源
相同的请求地址不同的响应资源,这种资源就是动态资源。
十二、Node.js异步编程
12.1 同步API,异步API
- 同步API: 只有当前API执行完成后,才能继续执行下一个API
- 异步API: 当前API的执行不会阻塞后续代码的执行。
12.2 同步API,异步API的区别(获取返回值)
同步API可以从返回值中拿到API执行的结果,但是异步API是不可以的。
例子:新建getReturnValue.js文件:
//同步
function sum(n1, n2) {
return n1 + n2;
}
const result = sum(10, 20);
console.log(result); //结果30
例子:新建callback.js文件;
//异步
function getData() {
setTimeout(function () {
return {
msg: 'hello node.js'
}
}, 2000)
}
const msg = getData();
console.log(msg); //结果undefined
结论:在异步API里,我们无法通过返回值的方式,去拿到异步API的执行结果。需要通过回调函数。
12.3 回调函数
自己定义函数让别人去调用。
// getData 函数定义
function getData (callback) {}
// getData 函数调用
getData(() => {});
例子:修改callback.js文件
function getData(callback) {
setTimeout(function () {
callback({
msg: 'hello node.js'
})
}, 2000)
}
getData(function (data) {
console.log(data); //结果 { msg: 'hello node.js' }
})
12.4 同步API,异步API的区别(代码执行顺序)
- 同步API从上到下依次执行,前面代码会阻塞后面代码的执行。
- 异步API不会等待API执行完成后再向下执行代码。
12.5 Node.js中的异步API
fs.readFile 就是异步API。
fs.readFile('./demo.txt', (error, result) => { });
事件监听 也是异步API。
const app = http.createServer();
app.on('request', (req, res) => { });
如果异步 API 后面代码的执行依赖当前异步 API 的执行结果,但实际上后续代码在执行的时候异步 API 还没有返回结果,这个问题要怎么解决?
例子:需求:依次读取A文件、B文件、C文件
新建1.txt、2.txt、3.txt:里面分别写入1、2、3
创建 callbakehell.js 文件:
const fs = require('fs');
fs.readFile('./1.txt', 'utf8', (err, result1) => {
console.log(result1);
fs.readFile('./2.txt', 'utf8', (err, result2) => {
console.log(result2);
fs.readFile('./3.txt', 'utf8', (err, result3) => {
console.log(result3);
})
})
})
输出结果:
证明确实是依次读取文件内容。
但是这种嵌套形式的话,如果嵌套的层数过多,维护起来会很麻烦。这种回调嵌套回调再嵌套回调,我们比作为:回调地狱。
12.6 Promise
promise出现的目的是解决Node.js异步编程中回调地狱的问题。
基础语法:
let promise = new Promise((resolve, reject) => {
setTimeout(function () {
if (true) {
resolve({ name: '张三' })
} else {
reject('错误信息');
}
}, 2000)
})
promise.then(result => {
console.log(result);
})
.catch(err => {
console.log(err);
})
例子:
新建promise.js文件:
const fs = require('fs');
let promise = new Promise((resolve, reject) => {
fs.readFile('./1.txt', 'utf8', (err, result1) => {
if (err != null) {
reject(err);
} else {
resolve(result1);
}
})
})
promise.then(result => {
console.log(result);
})
.catch(err => {
console.log(err);
})
结果输出正确: 1
下面要解决依次读取文件例子的回调地狱的问题:
新建promise2.js文件:
const fs = require('fs');
// fs.readFile('./1.txt', 'utf8', (err, result1) => {
// console.log(result1);
// fs.readFile('./2.txt', 'utf8', (err, result2) => {
// console.log(result2);
// fs.readFile('./3.txt', 'utf8', (err, result3) => {
// console.log(result3);
// })
// })
// })
function p1() {
return new Promise((resolve, reject) => {
fs.readFile('./1.txt', 'utf8', (err, result) => {
resolve(result)
})
})
}
function p2() {
return new Promise((resolve, reject) => {
fs.readFile('./2.txt', 'utf8', (err, result) => {
resolve(result)
})
})
}
function p3() {
return new Promise((resolve, reject) => {
fs.readFile('./3.txt', 'utf8', (err, result) => {
resolve(result)
})
})
}
p1().then(res1 => {
console.log(res1);
return p2();
}).then(res2 => {
console.log(res2);
return p3();
}).then(res3 => {
console.log(res3);
})
p1.then 里 return 了一个 p2 的调用,p2 的调用返回一个 promise 对象,也就是说实际上 return 了一个 promise 对象。在下一个 then 里就能拿到上一个 then 里面 return 的 promise 对象的结果。
输出结果:
1
2
3
12.7 异步函数
异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了
基础语法:
function fn = async () => {};
或
async function fn() {}
- 在普通函数定义的前面加上async 关键字,普通函数就变成了异步函数。
- 异步函数默认的返回值是 promise对象,不是undefined。
例如:
async function fn() {
return '123';
}
console.log(fn());
结果是:
修改下代码:
async function fn() {
return '123';
}
// console.log(fn());
fn().then((data) => {
console.log(data)
})
结果是:
- 而错误信息用throw 来抛出返回,throw一旦被执行以后,后面的代码就不会再执行了。用.catch来捕获 throw 抛出的错误信息。
async function fn() {
throw '发生了一些错误';
return '123';
}
// console.log(fn());
fn().then((data) => {
console.log(data)
}).catch(err => {
console.log(err);
})
输出结果是:
await关键字
- 它只能出现在异步函数中
- await promise 它可以暂停异步函数的执行,等待promise对象返回结果后,再向下执行函数
例子: 还是依次读取文件
const fs = require('fs');
async function p1() {
return 'p1';
}
async function p2() {
return 'p2';
}
async function p3() {
return 'p3';
}
async function run() {
let r1 = await p1();
let r2 = await p2();
let r3 = await p3();
console.log(r1);
console.log(r2);
console.log(r3);
}
run();
运行结果:
总结
async 关键字:
1、普通函数定义前加 async 关键字,普通函数变成异步函数
2、异步函数默认的返回 promise 对象
3、在异步函数内部使用 return 关键字进行结果返回,结果会被包裹的 promise 对象中 return 关键字代替了 resolve 方法
4、在异步函数内部使用 throw 关键字抛出错误异常
5、使用异步函数再链式调用 then 方法获取异步函数执行的结果
6、调用异步函数再链式调用 catch 方法获取异步函数执行的错误信息
await 关键字:
1、await 关键字只能出现在异步函数中
2、await promise :await 后面只能写 promise 对象,写其他类型的 API 是不可以的
3、await 关键字可以暂停异步函数向下执行,直到 promise 对象返回结果
例子:通过 await 关键字,改造依次读取三个文件的例子。
fs.readFile() 方法是通过返回值的方式,来获取文件的读取结果,也就是说它不返回 promise 对象。node 提供了一个 promisify 方法,这个方法存储在 util 模块中,然后用这个 promisify 方法,对 readFile 进行包装,让它返回 promise 对象。
const fs = require('fs');
//promisify 方法是用来改造现有异步函数 API,让其返回 promise 对象
const promisify = require('util').promisify;
//调用 promisify 方法改造现有异步 API,让其返回 promise 对象
const readFile = promisify(fs.readFile);
async function run() {
let r1 = await readFile('./1.txt', 'utf8');
let r2 = await readFile('./2.txt', 'utf8');
let r3 = await readFile('./3.txt', 'utf8');
console.log(r1);
console.log(r2);
console.log(r3);
}
run();
输出结果: