回调地狱
Promise
为了解决回调地狱的问题
Promise基本概念
1.promise是一个构造函数
可以通过
new Promise()
创建Promise实例2.Promise.prototype中包含一个.then()方法
每一次
new Promise()
构造函数得到的实例对象,都可以通过原型链的方式访问then()方法3.
.then()
方法用来预先指定成功和失败的回调函数p.then( 成功的回调函数,失败的回调函数 )
p.then( result=>{}, error=>{} )
调用then方法,成功的回调函数是必须的,失败的回调函数是可选的
基于then-fs读取文件
由官方提供的fs模块仅支持以回调函数的方式读取文件,不支持Promise的调用方式。
安装then-fs
npm install then-fs
调用then-fs提供的readFile方法,可以异步读取文件,返回值为Promise的实例对象,可以调用then方法为每个Promise对象指定成功和失败的回调函数。
由于是异步读取,所以无法确定顺序。
上一个then方法中返回一个Promise对象,则可以通过下一个then继续进行处理,通过then方法的链式调用解决回调地狱问题。
import thenFs from 'then-fs' thenFs.readFile( './1.txt', 'utf-8' ).then( result => { console.log(result) return thenFs.readFile( './2.txt', 'utf-8' ) } ).then( result => { console.log(result) return thenFs.readFile( './3.txt', 'utf-8' ) } ).then( result => { console.log(result) } )
11111 22222 3333333
通过 .catch 捕获错误
在Promise的链式操作中如果发生了错误,可以使用 Promise.prototype.catch
方法进行捕获和处理:
import thenFs from 'then-fs' // 11.txt文件不存在 // 文件不存在导致读取失败,后面的3个 .then 都不会执行 // 错误会被 .catch 捕获 thenFs.readFile( './11.txt', 'utf-8' ).then( result => { console.log(result) return thenFs.readFile( './2.txt', 'utf-8' ) } ).then( result => { console.log(result) return thenFs.readFile( './3.txt', 'utf-8' ) } ).then( result => { console.log(result) } ).catch( err => { console.log( err.message ) } )
ENOENT: no such file or directory, open 'D:\桌面文件\文件\nodejs\ES6模块化\11.txt'
如果不希望前面的错误导致后面的.then 无法执行,则可以将 .catch 的调用提前,示例:
import thenFs from 'then-fs' // 11.txt文件不存在 // 错误会被 .catch 捕获 // 错误已经被捕获,不会影响后面的 .then thenFs.readFile( './11.txt', 'utf-8' ) .catch( err => { console.log( err.message ) } ) .then( result => { console.log(result) return thenFs.readFile( './2.txt', 'utf-8' ) } ) .then( result => { console.log(result) return thenFs.readFile( './3.txt', 'utf-8' ) } ) .then( result => { console.log(result) } )
undefined 22222 3333333
Promise.all()
方法
Promise.all()方法会发起并行的Promise异步操作,等所有的异步操作全部结束后才会执行下一步的 .then()操作(等待机制)。示例:
import thenFs from 'then-fs' const promiseArr = [ thenFs.readFile( './1.txt', 'utf8' ), thenFs.readFile( './2.txt', 'utf8' ), thenFs.readFile( './3.txt', 'utf8' ), ] // 先执行完异步事件数组中的全部事件,才会执行then方法中的处理函数 // then方法中的处理函数的参数与异步事件的顺序一致 Promise.all( promiseArr ).then( ([r1,r2,r3]) => { console.log( r1, r2, r3 ) } ).catch( err => { console.log( err.message ) } )
11111 22222 3333333
**注意:**数组中的Promise实例顺序,就是最终结果的顺序。
Promise.race()
方法
Promise.race()
方法会发起并行的Promise异步操作,只要任何一个异步操作完成就执行下一步的 .then 操作(赛跑机制),示例:
import thenFs from 'then-fs' const promiseArr = [ thenFs.readFile( './1.txt', 'utf8' ), thenFs.readFile( './2.txt', 'utf8' ), thenFs.readFile( './3.txt', 'utf8' ), ] Promise.race( promiseArr ).then( (r) => { console.log( r ) } ).catch( err => { console.log( err.message ) } )
只要有文件完成读去就会进入then方法,输出为最先完成读取的文件的内容。
PS D:\桌面文件\文件\nodejs\ES6模块化> node .\then.js 11111 PS D:\桌面文件\文件\nodejs\ES6模块化> node .\then.js 11111 PS D:\桌面文件\文件\nodejs\ES6模块化> node .\then.js 11111 PS D:\桌面文件\文件\nodejs\ES6模块化> node .\then.js 3333333 PS D:\桌面文件\文件\nodejs\ES6模块化> node .\then.js 11111 PS D:\桌面文件\文件\nodejs\ES6模块化> node .\then.js 22222
基于Promise封装读取文件的方法
方法封装的要求:
1.方法的名称定义为getFile
2.方法接收一个形参fpath,表示要读取的文件的路径。
3.方法的返回值为Promise实例对象
import thenFs from 'then-fs' /** * 基于Promise封装的读取文件的方法 * @param {*} fpath 要读取文件的路径 * @returns 返回一个Promise实例对象 */ function getFile( fpath ) { // 要想创建具体的异步操作,要在 new Promise() 构造函数中传递一个函数 // 将具体的异步操作定义到函数中 // 通过then方法指定的成功和失败的回调函数,可以在function的形参中进行接收 // reject 为失败的回调函数 // resolve 为成功的回调函数 return new Promise( function( resolve, reject ) { // 一个具体的异步操作 thenFs.readFile( fpath, 'utf8', (err, dataStr) => { if ( err ) return reject(err) return resolve(dataStr) } ) } ) } // 第一个回调函数为成功的回调函数 // 第二个回调函数为失败的回调函数 getFile( './1.txt' ).then( data=>console.log(data), err=>console.log(err.message) )
11111