关于异步和同步
Promise简介
- Promise对象可以解决回调地狱的问题
回调地狱:如果我们希望几个异步请求按照顺序来执行,那么就需要将这些异步操作嵌套起来,嵌套的层数特别多,就会形成回调地狱 或者叫做 横向金字塔。
异步请求嵌套还有一个问题就是性能问题。也就是所需时间过多,基本上失去了异步任务的特点
- Promise 是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理和更强大
Promise可以理解为一个容器,里面可以编写异步程序的代码
- 从语法上说,Promise 是一个对象,使用的使用需要
new
Promise使用
第一部分:包装异步任务
let p = new Promise((resolve, reject) => {
// 形参resolve,单词意思是 完成
// 形参reject ,单词意思是 失败
// 这里放异步任务,把异步任务成功的结果传递给resolve,失败传给rejext
fs.readFile('./a.txt',(err,data)=>{
err? reject(err):resolve(data.length)
})
});
第二部分:获取异步任务结果
// p.then(函数1,函数2)
// 函数1:相当于前面的resolve 用于取得成功的结果
// 函数2:相当于前面的reject函数,用于取得失败的错误信息,函数2可选
p.then((r)=>{
console.log(r)//r就是前面resolve函数传递过来的结果
},(err)=>{
console.log(err)
})
promise对象后面都可以加catch
特点
简单来说就是多次调用 resolve 函数,只有第一次有效,其他的调用都无效。
const fs = require('fs');
// 1. 包装异步任务
let p = new Promise((resolve, reject) => {
resolve(123);
resolve(456); // 这次调用无效
});
// 2. 获取异步任务的结果
p.then(res => {
console.log(res); // 123
}, err => {
console.log(err);
});
- new Promise是同步执行的
- 获取结果时(调用 resolve 触发 then方法时)是异步的
then方法的链式调用
- 前一个then里面返回的字符串,会被下一个then方法接收到。但是没有意义;
- 前一个then里面返回的Promise对象,并且调用resolve的时候传递了数据,数据会被下一个then接收到
- 前一个then里面如果没有调用resolve,则后续的then不会接收到任何值
const fs=require('then-fs')
let p=fs.readFile('./a.txt')
let p1=fs.readFile('./b.txt')
p.then((r)=>{
console.log(r.length)//r就是前面resolve函数传递过来的结果
return p1
}).then((r1)=>{
console.log(r1.length)
}).catch((err) => {//catch 方法可以统一获取错误信息
console.log(err);
});
异步读取文件
第一种:封装函数
function myReadFile(path) {
return new Promise((resolve, reject) => {
fs.readFile(path, 'utf-8', (err, data) => {
err ? reject(err) : resolve(data.length);
})
});
}
myReadFile('./a.txt')
.then(a => {
console.log(a);
return myReadFile('./b.txt');
})
.then(b => {
console.log(b);
return myReadFile('./c.txt');
})
.then(c => {
console.log(c)
})
.catch((err) => {
console.log(err);
});
第二种:使用第三方模块读取文件
1.初始化 npm init - y
2.安装模块 npm i then-fs
3.读取文件后,返回 Promise 对象
4.修改 package.json ,添加 “type”: “module” 表示使用ES6的模块化语法
实例:
终端进行的操作:
1.初始化 npm init - y
2.安装模块 npm i then-fs
3.读取文件后,返回 Promise 对象
const fs=require('then-fs')
let p=fs.readFile('./a.txt')
let p1=fs.readFile('./b.txt')
p.then((r)=>{
console.log(r.length)//r就是前面resolve函数传递过来的结果
return p1
}).then((r1)=>{
console.log(r1.length)
}).catch((err) => {
console.log(err);
});
4.修改 package.json ,添加 “type”: “module” 表示使用ES6的模块化语法
async 和 await 修饰符
async 用于修饰一个 function
语法: let value = await promise对象;
const fs = require('fs');
// 将异步读取文件的代码封装
function myReadFile (path) {
return new Promise((resolve, reject) => {
fs.readFile(path, 'utf-8', (err, data) => {
err ? reject(err) : resolve(data.length);
});
}).catch(err => {
console.log(err);
});//对于错误处理,可以选择在async函数后面使用 `.catch()` 或 在promise对象后使用 `.catch()`
}
async function abc () {
let a = await myReadFile('./a.txt');
console.log(a);
}
abc();
由于await需要等待promise执行完毕,所以await会暂停函数的执行,但不会影响其他同步任务