前言
promise是Es6新增的,本身是一个构造函数,promise对象用来封装异步代码,可以获取成功/失败的返回值。promise的引入也是为了解决在异步js中回调函数嵌套太多,进而形成回调地狱的问题。(回调地狱的特点-不便于阅读-不利于维护)
例子
比如现在你玩一个游戏,进行闯关,一共有5个关卡,每一关需要时间为1秒,如果成功就会进入下一关卡,如果某个关卡失败就结束游戏,当5个关卡全部通过,就是通关。
用我们原生的js来实现就是
//这里我们用Math.round(Math.random())表示在0-1之间四舍五入,来决定是否能通过某个关卡。
setTimeout(()=>{
if(Math.round(Math.random())){
console.log("通过第一关");
setTimeout(()=>{
if(Math.round(Math.random())){
console.log("通过第二关");
setTimeout(()=>{
if(Math.round(Math.random())){
console.log("通过第三关");
setTimeout(()=>{
if(Math.round(Math.random())){
console.log("通过第四关");
setTimeout(()=>{
if(Math.round(Math.random())){
console.log("通过第五关");
console.log("恭喜你,通关啦。");
}else{
console.log("提示:就差最后一关没通过");
}
},1000)
}else{
console.log("提示:还剩两关没通过");
}
},1000)
}else{
console.log("提示:还剩三关没通过");
}
},1000)
}else{
console.log("提示:就通过了前两关卡,实力有点不行啊");
}
},1000)
}else{
console.log("提示:太菜了第一关都没过");
}
},1000)
复制代码
乍眼一看,我们这个代码实在有些头秃,非常不便于我们去阅读和维护。那么这个例子我们可以用promise方法来实现么?
Promise
Promise状态
Promise对象 本质上代表的是一个未完成,但预计将要完成的操作。 有三种状态: pending:初始值 fulfilled:成功的状态 rejected:失败的状态
promise构造函数中需要传入一个回调函数,该函数有两个参数:resolve和reject。
resolve函数:会将promise对象的状态从pending变为fulfilled。
reject函数:会将promise对象的状态从pending变为rejected。
复制代码
Promise方法
resolve
方法:他会返回一个成功状态的promise对象
let eg1 = Promise.resolve("ok");//OK可更改,自己定义的
console.log(eg1);
复制代码
reject
方法:他会返回一个失败状态的promise对象
let eg2 = Promise.reject("error");//error可更改,自己定义的
console.log(eg2);
复制代码
all
方法:接收一个包含多个promise对象的数组。 返回值:如果传入的promise对象都是成功的,返回一个成功的promise对象。只要有一个失败,则返回一个失败的promise对象。
let eg1 = Promise.resolve("ok1");
let eg2 = Promise.reject("error2");
let eg3 = Promise.resolve("ok3");
let eg4 = Promise.reject("error4");
let egall = Promise.all([eg1,eg3]);//结果1
let egall = Promise.all([eg1, eg3,eg2]);//结果2
复制代码
结果1 结果2 了解了这些我们来看看用promise如何实现我们上边的例子
// 封装一个方法
function getAllow(data,err) {
// 将promise对象return出去
return new Promise((resolve,reject) => {
setTimeout(() => {
if (Math.round(Math.random())) {
//成功
resolve(data)
} else {
//失败
reject(err)
}
}, 1000)
})
}
//结果是一个promise对象
getAllow("通过第一关","提示:太菜了第一关都没过").then((data)=>{
console.log(data);
return getAllow("通过第二关","提示:就通过了前两关卡,实力有点不行啊");
}).then((data)=>{
console.log(data);
return getAllow("通过第三关","提示:还剩三关没通过");
}).then((data)=>{
console.log(data);
return getAllow("通过第四关","提示:还剩两关没通过");
}).then((data)=>{
console.log(data);
return getAllow("通过第五关","提示:就差最后一关没通过");
}).then((data)=>{
console.log(data);
console.log("恭喜你,通关啦。");
}).catch((err)=>{
console.log(err);
})
复制代码
看到这个代码我们可以明显感觉到,简洁工整了许多。。。别急,这还没有结束✈
async
和await
async
async:异步,用来声明异步函数,该函数会返回一个promise对象。
async function fn(){
if (Math.round(Math.random())) {
// 默认返回一个成功状态的promise对象。 该对象的结果由 return来决定。
return "ok"
}else{
//抛出错误时,返回一个失败状态的promise对象
throw new Error("失败了")
}
}
let eg1 = fn();
eg1.then((data)=>{
//获取成功的值,在then的回调函数中定义一个形参接受。
console.log(data);//ok
}).catch((err)=>{
//获取失败的信息,在catch的回调函数中定义一个形参接受。
console.log(err);
})
console.log(eg1);
复制代码
await
await的用法:
- await关键字必须写在async函数中。但是async函数可以没有await。
- await右侧书写表达式,表达式一般返回值为promise对象。
- await返回的是promise成功的结果。
- await的promise失败了,就会抛出异常,可以通过tryCatch来处理异常。
const eg1 = new Promise((resolve,reject)=>{
if (Math.round(Math.random())) {
resolve("成功了")
} else {
reject("失败了")
}
});
async function fn(){
try {
// res的值就是promise成功的值。
let res = await eg1;
console.log(res); //成功了
} catch (error) {
// error就是promise对象失败时,传入的数据。
console.log(error); //失败了
}
}
fn();
复制代码
await
+async
来实现上述案例
function getAllow(data, err) {
// return出去一个promise对象
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.round(Math.random())) {
//成功了
resolve(data)
} else {
//失败了
reject(err)
}
}, 100)
})
}
async function main() {
try {
//如果成功,first变量中的就是成功后的结果 18行的data
let first = await getAllow("通过第一关", "提示:太菜了第一关都没过");
console.log(first);
let second = await getAllow("通过第二关", "提示:就通过了前两关卡,实力有点不行啊");
console.log(second);
let thired = await getAllow("通过第三关", "提示:还剩三关没通过");
console.log(thired);
let fourth = await getAllow("通过第四关", "提示:还剩两关没通过");
console.log(fourth);
let fifth = await getAllow("通过第五关", "提示:就差最后一关没通过");
console.log(fifth);
console.log("恭喜你,通关啦。");
} catch (error) {
console.log(error);
}
}
main();
复制代码