回调地狱问题
首先,回调地狱并不是错误,没有语法错误。但是层层嵌套,代码不优雅
如何解决呢?
优化的方向就是 把异步的代码 外观上同步化
Promise关键字 承诺许诺
promise初体验
/*
首先,回调地狱并不是错误,没有语法错误。但是层层嵌套,代码不优雅
如何解决呢?
优化的方向就是 把异步的代码 外观上同步化
Promise关键字 承诺许诺
*/
const path = require('path')
const fs = require('fs')
const fil1 = path.join(__dirname, './test/a.txt')
const fil2 = path.join(__dirname, './test/b.txt')
const fil3 = path.join(__dirname, './test/c.txt')
fs.readFile(
fil1, 'utf-8', (error, data1) => {
if (error) {
return console.log(error.message);
}
// 读取成功
fs.readFile(
fil2, 'utf-8', (error2, data2) => {
if (error) {
return console.log(error2.message);
}
fs.readFile(
fil3, 'utf-8', (error3, data3) => {
if (error) {
return console.log(error3.message);
}
// 输出读取到的数据
// console.log('读取成功!');
// console.log(data1 + data2 + data3);
}
)
}
)
}
)
// console.log('================================');
// 使用promise对象解决回调地狱问题
// 1. 创建 Promise对象
// 箭头函数里面两个形参,两个形参是两个函数,
// 成功执行第一个函数,失败执行第二个
// new Promise( (resolve,reject)=>{} )
let p1 = new Promise((resolve, reject) => {
// 同步的代码放在这里,但是一般不会放同步的代码
fs.readFile(fil1, 'utf-8', (error, data) => {
if (error) {
// 读取失败。执行reject函数
return reject(error)
}
// 读取成功 执行resolve函数
resolve(data)
})
})
// 书写回调函数
// new Promise().then(成功后执行的函数,失败后执行的函数)
p1.then(
(data) => {
// 打印读取成功后的数据
console.log(data);
},
(error) => {
// 读取失败,打印错误信息
console.log(error.message);
}
)
promise的then方法的链式书写
// new Promise().then() 的链式调用
const path = require('path')
const fs = require('fs')
const fil1 = path.join(__dirname, './test/a.txt')
const fil2 = path.join(__dirname, './test/b.txt')
const fil3 = path.join(__dirname, './test/c.txt')
let p1 = new Promise((resolve, reject) => {
// 同步的代码放在这里,但是一般不会放同步的代码
fs.readFile(fil1, 'utf-8', (error, data) => {
if (error) {
// 读取失败。执行reject函数
return reject(error)
}
// 读取成功 执行resolve函数
resolve(data)
})
})
// then的链式调用,第一个then函数执行后,无论成功与否,都会执行后续的then函数
// then函数里面的两个函数参数,都可以有返回值,返回值会被下一个then里面的函数形参接收
// 如果返回值是promise对象,下一个then里面函数的形参接收的不是这个promise对象,而是这个promise对象内部的调用resolve函数的参数或者reject函数的参数
p1.then(
(data) => {
// 打印读取成功后的数据
console.log(data);
// return '读取成功'
return p1
},
(error) => {
// 读取失败,打印错误信息
console.log(error.message);
}
).then((data) => {
console.log(data);
console.log('我是第二个then');
}, () => {
})
使用promise完成多文件读写操作
// new Promise().then() 的链式调用
const path = require('path')
const fs = require('fs')
const fil1 = path.join(__dirname, './test/a.txt')
const fil2 = path.join(__dirname, './test/b.txt')
const fil3 = path.join(__dirname, './test/c.txt')
let p1 = new Promise((resolve, reject) => {
fs.readFile(fil1, 'utf-8', (error, data) => {
if (error) {
// 读取失败。执行reject函数
return reject(error)
}
// 读取成功 执行resolve函数
resolve(data)
})
})
let p2 = new Promise((resolve, reject) => {
fs.readFile(fil2, 'utf-8', (error, data) => {
if (error) {
// 读取失败。执行reject函数
return reject(error)
}
// 读取成功 执行resolve函数
resolve(data)
})
})
let p3 = new Promise((resolve, reject) => {
fs.readFile(fil3, 'utf-8', (error, data) => {
if (error) {
// 读取失败。执行reject函数
return reject(error)
}
// 读取成功 执行resolve函数
resolve(data)
})
})
let str = ''
// 如果返回值是promise对象,下一个then里面函数的形参接收的不是这个promise对象,而是这个promise对象内部的调用resolve函数的参数或者reject函数的参数
p1.then(
(data) => {
str += data;
// 读取第二个文件
return p2
},
(error) => {
// 读取失败,打印错误信息
console.log(error.message);
}
).then(
(data) => {
str += data;
// 读取第三个个文件
return p3
},
(error) => {
// 读取失败,打印错误信息
console.log(error.message);
}
).then(
(data) => {
str += data;
// 输出读取到的文件内容
console.log(str);
},
(error) => {
// 读取失败,打印错误信息
console.log(error.message);
}
);
使用util内置模块结合promise更优雅的完成文件读写
// 导入util
const util = require('util')
const path = require('path')
const fs = require('fs')
const fil1 = path.join(__dirname, './test/a.txt')
const fil2 = path.join(__dirname, './test/b.txt')
const fil3 = path.join(__dirname, './test/c.txt')
/*
传入一个遵循常见的错误优先的回调风格的函数
(即以一个 (err, value) => ... 回调作为最后一个参数),
并且返回一个返回 promise 的版本。
什么是错误优先: 比如 if (error) 作为第一个判断
*/
// 使用util.promisify() 返回一个Promise对象
let readFilePromise = util.promisify(fs.readFile);
// 上面的一行代码 就会把对象包装成下面的这种样子
/* function readFilePromise(filePath){
return new Promise((resolve, reject) => {
fs.readFile(filePath, 'utf-8', (error, data) => {
if (error) {
// 读取失败。执行reject函数
return reject(error)
}
// 读取成功 执行resolve函数
resolve(data)
})
})
} */
// 如果需要将最后读取的内容写入到文件中,只需要更改传递到promisify对象的参数即可
let writeFilePromise = util.promisify(fs.writeFile)
// 接收读取的内容
let str = ''
// 如果返回值是promise对象,下一个then里面函数的形参接收的不是这个promise对象,而是这个promise对象内部的调用resolve函数的参数或者reject函数的参数
readFilePromise(fil1).then(
(data) => {
str += data;
// 读取第二个文件
return readFilePromise(fil2)
},
(error) => {
// 读取失败,打印错误信息
console.log(error.message);
}
).then(
(data) => {
str += data;
// 读取第三个个文件
return readFilePromise(fil3)
},
(error) => {
// 读取失败,打印错误信息
console.log(error.message);
}
).then(
(data) => {
str += data;
// 输出读取到的文件内容
console.log(str);
// 读取成功,将内容写入到文件中
return writeFilePromise(path.join(__dirname,'./test/data.txt'),str)
},
(error) => {
// 读取失败,打印错误信息
console.log(error.message);
}
).then(()=>{
console.log('写入数据成功!');
},(error)=>{
console.log(error.message);
})