目录
Promise对象
Promise中的同步异步
使用Promise解决回调地狱
Promise封装
第三方then-fs解决回调地狱
async和await关键字
async关键字
await关键字
async和await解决回调地狱
4. async和await读取JSON文件案例
ES6新增的一个对象,主要是用来解决异步代码无法将值返回 ,所以新增了一个Promise对象
// 导入 fs 模块
import fs from 'fs';
// 创建Promise对象, 参数是一个函数,有两个形参;
// resolve: 通过,一般用于处理成功后的数据;
// reject : 拒绝,一般用于处理失败后的数据;
const p1 = new Promise((resolve, reject) => {
// 在函数中,一定要有异步代码;
fs.readFile('./txt/a.txt', 'utf8', (err, data) => {
// 原来,我们的data和err都无法通过return返回到 fs.readFile() 外面;
if (err == null) {
// 没有错误,就把读取到的信息,通过resolve放到fs.readFile() 外面;
resolve(data);
} else {
// 有错误,就把错误通过 reject 放到fs.readFile() 外面;
reject(err);
}
})
});
p1.then(res => console.log(res));
// p1里面就存储着 resolve 和 reject 抛出的值!
// // then() 可以接收两个参数,第一个函数处理成功,第二个函数处理失败;
// p1.then(res => {
// console.log(res);
// }, err => {
// console.log(err.message);
// });
// p1.then(res => {
// console.log(res);
// }).catch(err => {
// console.log('文件读取错误: ' + err.message);
// });
注意点:
new Promise()
必须传入一个函数作为Promise的参数, 这个函数在new Promise的时候就会执行
函数有resolve 和 reject 两个形参
函数就相当于一个容器,可以将异步代码认为放到这里
将异步任务成功的结果传给resovle函数,将失败的信息传给reject函数
p1.then(res => {
console.log(res);
}, err => {
console.log(err.message);
});
p1.then(res => {
console.log(res);
}).catch(err => {
console.log('文件读取错误: ' + err.message);
});
// 或者
p.then(
result => { /* 获取成功的结果 */ }
).catch(
err => { /* 获取失败的结果 */ }
);
注意点:
then方法接收以函数类型的参数,只处理成功
then方法接收两个函数类型的参数,分别用于接收resolve的值和reject的值
then方法也可以只接收一个参数,表示只接受resolve的值,失败的结果可以通过链式编程调用catch方法捕获
new Promise 和new 其他对象一样,是同步任务
获取结果时(调用resolve 触发then方法时)是异步的
// 导入 fs 模块
import fs from "fs";
// 创建Promise对象;
const p1 = new Promise((resolve, reject) => {
fs.readFile('./txt/a.txt', 'utf8', (err, data) => {
resolve(data); // 不做判断,不考虑错误情况;
});
});
const p2 = new Promise((resolve, reject) => {
fs.readFile('./txt/b.txt', 'utf8', (err, data) => {
resolve(data); // 不做判断,不考虑错误情况;
});
});
const p3 = new Promise((resolve, reject) => {
fs.readFile('./txt/c.txt', 'utf8', (err, data) => {
resolve(data); // 不做判断,不考虑错误情况;
});
});
// 读取文件
const a = p1.then(res => {
console.log(res);
// then()中的回调函数,不写返回值,默认返回一个空白的Promise对象,如果返回一个真实的Promise对象,那么就会赋值给 then();
return p2;
})
const b = a.then(res => {
console.log(res);
// 返回一个 Promise 对象,调用下一个 then();
return p3;
})
const c = b.then(res => {
console.log(res);
});
// 导入 fs 模块
import fs from 'fs';
// 封装一个方法,返回一个 Promise 对象;
function getPromise(url) {
return new Promise((resolve, reject) => {
fs.readFile(url, 'utf8', (err, data) => {
resolve(data); // 不做判断,不考虑错误情况;
});
});
};
// 调用
getPromise('./txt/a.txt').then(res => {
console.log(res);
return getPromise('./txt/b.txt');
}).then(res => {
console.log(res);
return getPromise('./txt/c.txt');
}).then(res => {
console.log(res);
});
// 注意: 现在是条件不允许,我们自己封装,将来条件好了,让别人封装,我们调用就可以了!
// // 普通fs模块,readFile()返回 undefined ;
// // then-fs模块,readFile()返回 Promise 对象;
// import fs from 'fs';
// const a = fs.readFile('./txt/a.txt', 'utf8', () => {});
// console.log(a);
// // 下载: npm i then-fs
// import thenFs from 'then-fs';
// const b = thenFs.readFile('./txt/a.txt', 'utf8');
// console.log(b);
// 导入模块
import thenFs from 'then-fs';
// 读取文件
thenFs.readFile('./txt/a.txt', 'utf8').then(res => {
console.log(res);
return thenFs.readFile('./txt/b.txt', 'utf8');
}).then(res => {
console.log(res);
return thenFs.readFile('./txt/c.txt', 'utf8');
}).then(res => {
console.log(res);
});
// 未来,很多第三方模块,都是支持Promise对象开发的;
async 和await 是ES2017中提出来的,async 和await两个关键字的出现,简化了Promise对象的使用
async用于修饰一个function
async修饰的函数,总是返回的一个Promise对象
函数内的所有值,将自动包装在resolved的Promise中
await只能出现在异步函数中
await能暂停代码执行,让后面的同步代码先执行
await后面跟随的是一个Promise对象
await返回的是Promise对象中的then()中的回调函数中的参数res
// then-fs导入
import thenFs from 'then-fs';
// 定义一个用async修饰的函数
async function fn() {
// 按照顺序读取文件信息
const str1 = await thenFs.readFile('./txt/a.txt', 'utf8');
console.log(str1);
const str2 = await thenFs.readFile('./txt/b.txt', 'utf8');
console.log(str2);
const str3 = await thenFs.readFile('./txt/c.txt', 'utf8');
console.log(str3);
}
// 函数不调用,不执行
fn();
// 封装四个方法: 增删改查; 要求返回信息;
// 利用:await + async + then-fs + es6模块化
// 0.导入模块
import fs from 'then-fs';
// 1.查询 - 提示: 返回的数据数据,被放入了 Promise 对象中!
async function getData() {
// 读取信息 // await 必须出现在 async 修饰的函数中
const str = await fs.readFile('./data.json', 'utf8');
return JSON.parse(str);
}
// // 测试
// getData().then(res => {
// console.log(res);
// });
// 2.添加 - 返回一个 Promise 对象;
async function addData(obj) {
try {
// 把Promise对象中的值取出来;
const arr = await getData();
// 向数组中添加数据
obj.id = arr[arr.length - 1].id + 1;
arr.push(obj);
// 写入
fs.writeFile('./data.json', JSON.stringify(arr));
return '添加成功';
} catch (e) {
return '添加失败';
}
}
// // 测试
// addData({
// "author": "大刘",
// "bookname": "三体2",
// "publisher": "湖北人民出版社"
// }).then(res => {
// console.log(res);
// })
// 3.删除 - 返回一个 Promise 对象;
async function delData(id) {
try {
// 获取数组
const arr = await getData();
// 删除元素id,和传递的id值相同的那一项
// 过滤新数组,传递过来的id值,和元素的id值不相同,才有资格放入新数组;
const newArr = arr.filter(ele => id != ele.id);
// 写入文件 - 写入新数组!
fs.writeFile('./data.json', JSON.stringify(newArr));
return '删除成功';
} catch (e) {
return '删除失败';
}
}
// // 测试 - id如果不存在,不会引起错误!
// delData(6).then(res => {
// console.log(res);
// });
// 4.修改 - 返回一个 Promise 对象;
async function updateData(obj) {
try {
// 获取数组
const arr = await getData();
// 获取索引值,删除元素,添加元素;
const index = arr.findIndex(ele => ele.id == obj.id);
arr.splice(index, 1, obj);
// 写入文件
fs.writeFile('./data.json', JSON.stringify(arr));
// 返回
return '修改成功';
} catch (e) {
console.log(e.message);
return '修改失败';
}
}
// // 测试
// updateData({
// "author": "刘慈欣",
// "bookname": "三体3-死神永生",
// "publisher": "湖北人民出版社",
// "id": 5
// }).then(res => {
// console.log(res);
// });
// 导出
export default {
getData, addData, delData, updateData
}