then-fs的基本使用
可以通过node下载then-fs。 npm install then-fs
调用then-fs提供的readFile( ) 方法,可以异步读取文件的内容,它的返回值是一个Promise实例对象。因而可以调用.then( )方法为每个Promise异步操作指定成功和失败的回调函数
// 基于promise的方式读取文件 import thenFs from 'then-fs' // 使用默认导入从then-fs中导入默认共享的成员用thenFs接收 thenFs.readFile('./files/1.txt', 'utf8').then(r1 => {console.log(r1)}, err1 => {console.log(err1.message)} ) // .then里面分别是成功和失败的回调函数,用r1接收读取的结果 thenFs.readFile('./files/2.txt', 'utf8').then(r2 => {console.log(r2)}, err2 => {console.log(err2.message)} ) thenFs.readFile('./files/3.txt', 'utf8').then(r3 => {console.log(r3)}, err3 => {console.log(err3.message)} )
注意:上述代码无法保证文件的读取顺序!(读取文件顺序与代码顺序不一致)
.then( )方法的特性
.then( )方法的返回值也是一个Promise对象,对象状态由回调函数的执行结果决定
- 若回调函数中返回的结果是 非Promise类型的数据,则.then()方法返回的promise对象状态为成功,且回调函数的返回值就是该对象的成功值
- 回调函数中无返回值,则默认返回的就是undefined,也是 非Promise类型的数据
- 若回调函数中返回的结果 是Promise类型的数据(Promise对象),则.then()返回的Promise对象的状态由 内部回调函数返回的Promise对象的状态决定,且成功的值或者失败的值也相同
使用下一个.then( )方法进行处理**。通过.then( )方法的链式调用,解决了回调地狱的问题 **
thenFs.readFile('./files/1.txt','utf8') // 返回值是一个Promise对象 .then((r1)=>{ // 通过.then()为第一个Promise实例指定成功之后的回调函数 console.log(r1) return thenFs.readFile('./files/2.txt','utf8') // 在第一个.then()中返回一个新的Promise对象 }) .then((r2)=>{ // 继续调用.then()为上一个.then()的返回值指定成功之后的回调函数 console.log(r2) return thenFs.readFile('./files/3.txt','utf8') // 第二个.then中返回另一个新的Promise对象 }) .then((r3)=>{ console.log(r3) })
案例:同时读取多个文件(模拟多层嵌套的方式,实际上并不会这么写)
const fs = require('fs') // 使用Promise实现 const p = new Promise((resolve, reject)=>{ fs.readFile('./resources/为学.md', (err,data)=>{ resolve(data) }) }) // 调用.then()方法时,失败的回调函数是可选的 p.then(value =>{ // 这里value就是上面读取为学.md的结果 return new Promise((resolve, reject)=>{ // then里面返回一个新的Promise对象,防止读取第二个和第三个文件的时候产生回调地狱 fs.readFile('./resources/插秧诗.md', (err,data)={ // 这里的data就是读取到的插秧诗.md的结果 resolve([value, data]) // 把读取的两个内容进行合并,放在数组里继续向下传递 }) }) }).then(value => { // 这里的value就是接收上面两个文件合并的数组 return new Promise((resolve, reject)=>{ fs.readFile('./resources/观书有感.md', (err, data)=>{ // data是读取到的观书有感.md value.push(data) // 将第三个读取的结果压入到数组中 resolve(value) // 将三个读取的数据合并的数组作为成功的值 }) }) }).then(value =>{ console.log(value.join('\r\n')) // 将数组转化为字符串,\r\n就是回车,join(\r\n)就是以回车分隔 })
通过.catch捕获错误
在Promise的链式操作中,如果出现了错误,可以使用Promise.prototype.catch方法进行捕获和处理
thenFs.readFile('./files/11.txt','utf8') // 返回值是一个Promise对象 .then((r1)=>{ // 通过.then()为第一个Promise实例指定成功之后的回调函数 console.log(r1) return thenFs.readFile('./files/2.txt','utf8') // 在第一个.then()中返回一个新的Promise对象 }) .then((r2)=>{ // 继续调用.then()为上一个.then()的返回值指定成功之后的回调函数 console.log(r2) return thenFs.readFile('./files/3.txt','utf8') // 第二个.then中返回另一个新的Promise对象 }) .then((r3)=>{ console.log(r3) }) .catch((err)=>{ console.log(err.message) // 第一个文件不存在,则直接跳转到.catch(),后面的.then都不执行 })
- 将.catch( )放在最后就会捕获到所有的错误
- 如果不希望前面的错误导致后面的.then( )无法正常执行,则可以将.cacth( )的调用提前
Promise.all()方法
Promise.all( )方法会发起并行的Promise异步操作,等所有Promise异步操作全部结束后才会执行下一步的.then操作 (等待机制)
语法:promise.all( promises )
promises是包含n个promise对象的数组,该方法返回的是一个新的promise,只有所有的promise都成功才成功,只要有一个失败了就直接失败
p1, p2, p3都成功,所以result也是成功状态,且成功的值是三者的成功值组成的数组。
若有一个失败了,result就是失败状态,且失败的值就是对应的promise对象的失败值
Promise.race()方法
Promise.race( )方法会发起并行的Promise异步操作,只要任何一个异步操作完成,就立即执行下一步的.then( )操作(赛跑机制)
promise.race()方法返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态