promise背景
js中常见的异步操作有,定时器,ajax请求,读文件,异步操作的结果只能通过回调函数获取
但是异步操作的结果顺序有不确定性
如果想要按照顺序获取结果就需要,在第一个异步的回调函数中执行第二个异步任务
如果异步操作多的话就会形成回调地狱
为了解决回调地狱,ES6中新增了 Promise概念
Promise基本概念
Promise是ES6中引入的一种新语法,用于解决异步编程的毁掉地狱问题
Promise支持链式调用,promise 提供了简洁的API
1)什么是promise
语法上:promise是一个构造函数,用来创建一个promise实例对象,new的实例对象代表一个异步操作
操作上:promise用来封装异步操作,,并获取到结果是失败还是成功
promise语法
读取文件
import fs from "fs";
// 1.创建promise 对象,来执行异步任务
const p = new Promise((resolve, reject) => {
// 执行异步代码
fs.readFile("./file/1.txt", "utf-8", (err, datastr) => {
if (err) {
// 失败的话手动调用 reject()函数
reject(err.message);
} else {
// 成功手动调用resolve()函数,将结果以参数形式传递
resolve(datastr);
}
});
});
// 实例对象可以调用 .then(成功的回调函数,失败的)
p.then(
(value) => {
console.log(value);
},
(reason) => {
console.log(reason);
}
);
发起ajax
const p = new Promise ((resolve,reject)=>{
const xhr = new XMLHttpRequest()
xhr.open('get','http:www.liulongbin.top:3006/api/getbooks')
xhr.send()
xhr.onreadystatechange = ()=>{
if(xhr.readyState === 4){
if(xhr.status === 200){
resolve(xhr.responseText)
} else {
reject()
}
}
}
})
p.then((result)=>{
console.log(result);
},(error)=>{
console.log(error);
})
promise的三种状态
创建出实例对象时,状态是pendding:待定 状态
成功后,执行resolve()时,是fulfilled:已兑现 状态
失败后,执行reject()时, 是rejected:已拒绝 状态
promise.then()
promise实例对象的函数执行完的返回值是一个promise对象,可以使用 .then() 方法,执行完 .then()方法后返回值还是一个promise对象,所以可以使用链式调用
import fs from 'fs'
function read (url) {
const p1 = new Promise((resolve,reject)=>{
fs.readFile(url,'utf8',(err,result)=>{
if(err){
reject(err.message)
} else {
resolve(result)
}
})
})
return p1
}
read('./file/1.txt').then((result)=>{
console.log(result);
return read('./file/2.txt')
}).then((r1)=>{
console.log(r1);
return read('./file/3.txt')
}).then((r2)=>{
console.log(r2);
})
Poromise.prototype.catch()方法
加入在很长的.then()链式调用中,有一个报错,我们很难捕捉到错误的位置,而且每一个 .then()都写上一个err函数代码太长,
就可以使用promi.catch() 方法来捕获报错,可以将.catch()写在代码最后
read('./file/1.txt').then((result)=>{
console.log(result);
return read('./file/2.txt')
}).then((r1)=>{
console.log(r1);
return read('./file/33.txt')
}).then((r2)=>{
console.log(r2);
}).catch((err)=>{
console.log(err);
})
Promise.all()方法
并发处理多个异步任务,所有任务都执行完成,才能得到结果。
如果其中一个报错,一个结果都得不到
const r1 = read('./file/1.txt')
const r2 = read('./file/2.txt')
const r3 = read('./file/3.txt')
Promise.all([r1,r2,r3]).then((resultArr)=>{
console.log(resultArr); // 拿到的是一个数组,所有都执行完才返回
}).catch((err)=>{
console.log(err);
})
Promise.race()方法
并发处理多个异步任务,只要有1个任务结束就能得到结果。race 比赛的意思。
const r1 = read('./file/1.txt')
const r2 = read('./file/2.txt')
const r3 = read('./file/3.txt')
Promise.race([r1,r2,r3]).then((result)=>{
console.log(result);
})
async/await
async/await 是ES8引入的新语法,用来简化promise异步操作
用async声明的函数,被称为异步函数,函数调用返回值是一个promise对象
await
[返回值] = await 表达式/ 具体的值
await后面一般跟一个promise对象,返回值是一个promise对象的处理结果
await只能在async函数里面使用
async和await结合使用
一般 async都会和await搭配使用
注意事项: 如果在函数中使用了await ,函数必须使用async修饰
await前面的代码会同步执行,await后面的代码会被异步执行
import thenFs from 'then-fs'
async function getAllFile() {
console.log(1)
const r1 = await thenFs.readFile('./files/1.txt', 'utf8')
console.log(r1)
const r2 = await thenFs.readFile('./files/2.txt', 'utf8')
console.log(r2)
const r3 = await thenFs.readFile('./files/3.txt', 'utf8')
console.log(r3)
console.log(2)
}
getAllFile() //1 文件1 文件2 文件3 2