我们看下promiser.js的代码如下:
const fs = require("fs")
const path = require("path")
function getFileByPath(fPath){
fs.readFile(fPath,'utf-8',(err,dataStr) => {
if (err) throw err
console.log("datastr",dataStr)
return dataStr
})
}
var ret = getFileByPath(path.join(__dirname,'./files/1.txt'))
console.log("ret",ret)
结果我们看下log输出如下:
zhiliaodeMBP:promise zhiliao$ node ./promiser.js
ret undefined
datastr 1231
在JavaScript的世界中,所有代码都是单线程执行的,因为读取文件是耗时操作,所以执行到getFileByPath时,还没有读取完毕文件内容会输出undefined
由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。异步执行可以用回调函数实现:
const fs = require("fs")
const path = require("path")
function getFileByPath(fPath,callback){
fs.readFile(fPath,'utf-8',(err,dataStr) => {
if (err) throw err
callback(dataStr)
})
}
getFileByPath(path.join(__dirname,'./files/1.txt'),function(data){
console.info(data)
})
我们看下结果
zhiliaodeMBP:promise zhiliao$ node ./promiser.js
1231
上述例子代码不完善,如果读取文件内容失败,也就是出现异常,我们怎么处理?
const fs = require("fs")
const path = require("path")
function getFileByPath(fPath,callback,errCallBack){
fs.readFile(fPath,'utf-8',(err,dataStr) => {
if (err) return errCallBack(err)
callback(dataStr)
})
}
getFileByPath(path.join(__dirname,'./files/1.txt'),function(data){
console.info(data)
},function(err){
if(err) return console.info(err.message)
})
我们看下测试结果,我们看到是捕获了异常:
zhiliaodeMBP:promise zhiliao$ node ./promiser.js
ENOENT: no such file or directory, open '/Users/zhiliao/zhiliao/vue/promise/files/11.txt'
以上是我们读取一个文件内容,如果我们连续读取多个文件内容呢?我们可以用一种循环嵌套的方式,但是嵌套的方法过于繁琐,我们可以利用es6中的新特性promise来实现
const fs = require("fs")
const path = require("path")
function getFileByPath(fpath){
var promise = new Promise(function(resolve,reject){
fs.readFile(fpath,"utf-8",(err,dataStr)=>{
if(err) return reject(err)
resolve(dataStr)
})
})
return promise
}
var promise = getFileByPath('./files/1.txt')
promise.then(function(data){
console.log(data,"~~~")
},function(err){
console.log(err.message,">>>>")
})
我们看下测试效果如下:
zhiliaodeMBP:promise zhiliao$ node ./promiser.js
1231 ~~~
我们简单梳理下这个promise例子的执行过程:
程序执行
1.首先加载getFileByPath
进内存,
2.然后getFileByPath('./files/1.txt')
调用该方法,执行getFileByPath方法内代码,执行readFile操作,这里是耗时操作
3.返回promise对象
4.promise.then传递回调函数
5.等待readFile执行完毕,执行回调函数
我们还可以通过如下的方式实现批量读取文件内容
只需要在第一次读取完毕后,进行返回一个promise,然后在继续.then操作即可
function getFileByPath(fpath){
var promise = new Promise(function(resolve,reject){
fs.readFile(fpath,"utf-8",(err,dataStr)=>{
if(err) return reject(err)
resolve(dataStr)
})
})
return promise
}
var promise1 = getFileByPath('./files/1.txt')
promise1.then(function(data){
console.log(data,"~~~")
var promise2 = getFileByPath('./files/2.txt')
return promise2
},function(err){
console.log(err.message,">>>>")
})
.then(function(data){
console.log(data,"~~~")
},function(err){
console.log(err.message,">>>>")
})
如果连续读取2个文件的内容,如果第一个文件读取失败,那么我们不应该停止程序,应该让他继续读取第二个文件,这就需要我们自己收到在第一次读取失败时候,做失败处理
const fs = require("fs")
const path = require("path")
function getFileByPath(fpath){
var promise = new Promise(function(resolve,reject){
fs.readFile(fpath,"utf-8",(err,dataStr)=>{
if(err) return reject(err)
resolve(dataStr)
})
})
return promise
}
var promise1 = getFileByPath('./files/1但是.txt')
promise1.then(function(data){
console.log(data,"~~成功~")
return getFileByPath('./files/2.txt')
},function(err){
console.log(err,"~~失败~")
return getFileByPath('./files/2.txt')
})
.then(function(data){
console.log(data,"~~~")
},function(err){
console.log(err.message,">>>>")
})
测试结果如下:
zhiliaodeMBP:promise zhiliao$ node ./promiser.js{ [Error: ENOENT: no such file or directory, open './files/1但是.txt']
errno: -2, code: 'ENOENT', syscall: 'open',
path: './files/1但是.txt' } '~~失败~'wewr ~~~
只要有任何一个then语句出错,就终止全部语句
我们还可以利用catch语句块,不要在.then 里面去处理错误异常,而是需要在外面直接catch
const fs = require("fs")
const path = require("path")
function getFileByPath(fpath){
var promise = new Promise(function(resolve,reject){
fs.readFile(fpath,"utf-8",(err,dataStr)=>{
if(err) return reject(err)
resolve(dataStr)
})
})
return promise
}
var promise1 = getFileByPath('./files/1.txt')
promise1.then(function(data){
console.log(data,"~~成功~")
return getFileByPath('./files/2等待.txt')
})
.then(function(data){
console.log(data,"~~~")
})
.catch(function (err) { // catch 的作用: 如果前面有任何的 Promise 执行失败,则立即终止所有 promise 的执行,并 马上进入 catch 去处理 Promise中 抛出的异常;
console.log('这处理方式:' + err.message)
})
测试效果如下:
1231 ~~成功~
这是自己的处理方式:ENOENT: no such file or directory, open './files/2等待.txt'
zhiliaodeMBP:promise zhiliao$
{
"name":"safly",
"age":30
}