需求:封装一个方法,传入一个文件的路径,这个方法读取文件并且把内容返回给我
目录结构
|–1.txt
|–2.txt
|–3.txt
|–fun.js
引入相关的 node 模块 fs 和 path (node.js API里有说明)
const fs = require('fs')
const path = require('path')
读文件代码
fs.readfile(path(__diename,'./1.txt'),'utf-8',funciton(err.data){
if(err){
return err
}
return data
})
封装起来成一个函数
function getFile(filePath){
fs.readfile(filePath,'utf-8',funciton(err.data){
if(err){
return err
}
return data
})
}
var cont = getFile(.....)
console.log(cont)
以上的程序执行会报undefined,因为读文件是个异步操作,fs.readfile 直接丢进队列里,打印结果的时候,文件读取还没完成
那么怎么解决呢?
封装函数的时候,定义一个回调函数,
让异步里面的结果出来后,传给回调函数,我们从回调函数里拿要的值
function getFile(filePath,callback){ // 1
fs.readfile(filePath,'utf-8',funciton(err.data){ //这里有错误,要用es6箭头函数,不然this有问题?需要验证
if(err){
return callback(err)
}
callback(data) // 2
})
}
getFile('./1.txt',function(data){
console.log(data) // 3
})
以上封装也是不完善的,为什么呢?因为回调里面只接收一个参数,不一定知道里面的参数是成功的还是失败的
那么这样,给回调函数规定有2个参数,第一个是失败,第二个是成功
如果成功了,回调的第一个参数就是null
如果失败了,回调的第二个参数就是null
function getFile(filePath,callback){
fs.readfile(filePath,'utf-8',funciton(err.data){ //这里有错误,要用es6箭头函数,不然this有问题?需要验证
if(err){
return callback(err)
}
callback(null,data)
})
}
getFile('./1.txt',function(err,data){
if(err){
return console.log(err)
}
console.log(data)
})
这样还不完善,为什么呢?因为使用者看到这个函数 function getFile(filePath,callback) 是不知道回调里面有2个参数的,我们自己写的知道,使用者不知道
改进,给方法增加2个回调,一个成功的,一个失败的,这样一来,使用者就知道了
function getFile(filePath,succCb,errCb){
fs.readfile(filePath,'utf-8',funciton(err.data){ //这里有错误,要用es6箭头函数,不然this有问题?需要验证
if(err){
return errCb(err)
}
succCb(data)
})
}
getFile('./1.txt',function(suc){
console.log(suc)
},function(err){
console.log(err)
})
一个需求:先读文件1,再度文件2,再度文件3,这就产生了回调地狱
getFile('./1.txt',function(suc){
console.log(suc)
getFile('./2.txt',function(suc){
console.log(suc)
getFile('./3.txt',function(suc){
console.log(suc)
})
})
})
使用es6中的promise来解决回调地狱,把一层又一层的嵌套,改变成串联,翻译就是连写
打印
console.dir(Promise)
ƒ Promise()
all:ƒ all()
arguments:(...)
caller:(...)
length:1
name:"Promise"
prototype:Promise {constructor: ƒ, then: ƒ, catch: ƒ, finally: ƒ, Symbol(Symbol.toStringTag): "Promise"}
race:ƒ race()
reject:ƒ reject()
resolve:ƒ resolve()
Symbol(Symbol.species):(...)
get Symbol(Symbol.species):ƒ [Symbol.species]()
__proto__:ƒ ()
[[Scopes]]:Scopes[0]
Promise 里面有 prototype 里面有 then ,就是说,new 出来的 Promise 都可以使用 then 属性
既然 Promise 是一个实例,是一个异步操作,那么结果就只有两种状态:成功、失败。
由于reject()是一个异步操作,内部的操作,是无法通过 return 返回的(上面的读文件的例子说明了),这个时候就只能借助回调函数来拿到成功或失败的值。
成功了会调用 resolve()
失败了会调用 reject()
我们在 new 出来的 Promise 实例,调用 then() 方法,预先为这个 Promise 异步操作,指定成功和失败的回调函数
Promise 内部的 resolve() 和 reject() 是形参,.then()出来的是实参
怎么在 Promise 里写异步操作?
在一个 funtion 里写具体的异步操作
new Promise(function(resolve,reject){
在此处函数里写的就是异步操作
})
Promise 一个特点,只要 new 出来,就会执行,如下也会执行
var promise = new Promise(function(resolve,reject){
在此处函数里写的就是异步操作
})
这样不好,我需要在想用的时候才让它执行,那怎么办?满足这种要求的,只有函数,函数在调用的时候才执行,那么,把
promise 代码放进一个函数就可以了
function getText(){
var promise = new Promise(function(resolve,reject){
在此处函数里写的就是异步操作
})
}
getText()
配合.then使用
.then里面,成功的回调必须传,失败的可以省略
function getText(){
var promise = new Promise(function(resolve,reject){
fs.readfile('./1.txt','utf-8',(data,err)=>{
if(err) return reject(err)
return resolve(data)
})
})
return promise
}
getText().then(
function(data){
console.log(data)
},
function(err){
console.log(err)
}
)
想连续读取文件1、2、3
getText('1/txt').then(
function(data){
console.log(data)
return getText('2/txt')
}
).then(
function(data){
console.log(data)
return getText('3/txt')
}
).then(
function(data){
console.log(data)
}
)
如果前面的异步失败,那么后面的都不会执行,怎么解决这个问题
给异步加上失败的回调
在失败的回调里返回下一个异步操作
getText('1/txt').then(
function(data){
console.log(data)
return getText('2/txt')
},
function(err){
console.log(err)
return getText('2/txt')
}
).then(
function(data){
console.log(data)
return getText('3/txt')
},
function(err){
console.log(err)
return getText('3/txt')
}
).then(
function(data){
console.log(data)
}
)
.catch 错误捕获处理
就是说,任何一个错误出现了,马上中止执行,跳进catch中执行
getText('1/txt').then(
function(data){
console.log(data)
return getText('2/txt')
}
).then(
function(data){
console.log(data)
return getText('3/txt')
}
).then(
function(data){
console.log(data)
}
).catch(err){
console.log(err)
}