1. 什么是回调地狱
多层回调函数的相互嵌套,就会形成 回调地狱 ,示例代码:
回调地狱的代码耦合性太强,牵一发而动全身,难以维护;
大量冗余的代码相互嵌套,代码的可读性变差
为了 解决回调地狱 的问题,ES6(ECMAScript 2015)中新增了 Promise 的概念。
2.什么是 Promise
① Promise 是一个 构造函数:
-
可以创建 Promise 的实例 const p = new Promise() ;
-
new 出来的 Promise 实例对象,代表一个异步操作。
② Promise.prototype 上包含一个 .then() 方法:
- 每一次 new Promise() 构造函数得到的实例对象,都可以通过 原型链 的方式访问到 .then() 方法,例如 p.then()
③ .then() 方法用来预先指定成功和失败的回调函数:
-
p.then(成功的回调函数,失败的回调函数)
-
p.then(result => { }, error => { })
-
调用 .then() 方法时,成功的回调函数是必选的、失败的回调函数是可选的。
3. 基于 Promise 按顺序读取文件内容
3.1 基于回调函数按顺序读取文件内容
如下代码是基于回调函数按顺序读取文件内容:
3.2 then-fs 的基本使用
由于 node.js 官方提供的 fs 模块仅支持以回调函数的方式读取文件,不支持 Promise 的调用方式。
因此,需要先运行如下的命令,安装 then-fs 这个第三方包,从而支持基于 Promise 的方式读取文件的内容:
调用 then-fs 提供的 readFile() 方法,可以异步地读取文件的内容,它的返回值是 Promise 的实例对象。
因此可以调用 .then() 方法为每个 Promise 异步操作指定成功和失败之后的回调函数。示例代码如下:
但是上述的代码无法保证文件的读取顺序,需要做进一步的改进。
3.3 基于 Promise 按顺序读取文件的内容
其实.then() 方法有一个特性,如果上一个 .then() 方法中返回了一个新的 Promise 实例对象,则可以通过下一个 .then() 继续进行处理。
通过 .then() 方法的链式调用,就解决了回调地狱的问题,示例代码如下:
3.4 通过 .catch 捕获错误
在 Promise 的链式操作中如果发生了错误,可以使用 Promise.prototype.catch 方法进行捕获和处理:
如果不希望前面的错误导致后续的 .then 无法正常执行,则可以将 .catch 的调用提前,示例代码如下:
3.5 Promise.all() 方法
Promise.all() 方法会发起并行的 Promise 异步操作
等所有的异步操作全部结束后才会执行下一步的 .then 操作(等待机制)。示例代码如下:
3.6 Promise.race() 方法
Promise.race() 方法会发起并行的 Promise 异步操作
只要任何一个异步操作完成,就立即执行下一步的.then 操作(赛跑机制)。示例代码如下:
4. 基于 Promise 封装读文件的方法
方法的封装要求:
-
方法的名称要定义为 getFile ;
-
方法接收一个形参 fpath,表示要读取的文件的路径;
-
方法的返回值为 Promise 实例对象 。
第 5 行代码中的 new Promise() 只是创建了一个形式上的异步操作,如果想要创建具体的异步操作,则需要在 new Promise() 构造函数期间,传递一个 function 函数,将具体的异步操作定义到 function 函数内部。示例代码如下:
node.js 官方提供的 fs 模块仅支持以回调函数的方式读取文件:import fs from 'fs'
通过 .then() 指定的成功和失败的回调函数,可以在 function 的形参中进行接收,示例代码如下:
Promise 异步操作的结果,可以调用 resolve 或 reject 回调函数进行处理。示例代码如下: