目录
1、Promise
Promise是JS中进行异步编程的新解决方案(旧方案是单纯用回调函数),语法上来说它是一个构造函数;
Promise对象的特点
1)对象状态不受外界影响;Promise对象有三种状态:pending(进行中)、fulfilled(已成功)和reject(已失败)。只有异步操作的结果可以决定当前是哪一种状态;
2)一旦状态改变就不会再变,任何时候都可以得到这个结果;Promise对象的状态改变只有两种可能:从pending变为fulfilled和从pending变为rejected,只要这两种情况发生,状态凝固,称为resolved(已定型);
为什么使用Promise
1)指定回调函数的方式更加灵活
Promise:启动异步任务=>返回promise对象=>给promise对象绑定回调函数(甚至可以在异步任务结束后指定多个)
旧的:必须在启动任务前指定
2)支持链式调用,可以解决回调地狱问题
回调地狱:回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件
回调地狱的缺点:不便于阅读;不便于异常处理
解决方案:promise链式调用
2、Promise用法
1) resolve和reject
resolve:成功的回调,Promise状态变为fulfilled
reject:失败的回调,Promise状态变为rejected
2)then方法
then中有两个回调函数,第一个参数为resolve时的回调,第二个参数为reject时的回调
Promise.then()返回的仍是一个Promise对象,所以可以链式调用then方法
如果抛出异常,新的Promise变为rejected,reason为抛出的异常;
如果返回非Promise的任意值,新的Promise变为resolve,data为返回的值;
如果返回另一个Promise,此Promise的结果就会成为新Promise的结果;
3)catch方法
catch方法用来捕获异常,其参数为reject时的回调,返回一个新的Promise对象
<body>
<button id="btn">随机数</button>
</body>
<script>
var btn = document.getElementById('btn')
btn.addEventListener('click',()=>{
let n = Math.ceil(Math.random()*10)//1-10
let p = new Promise((resolve,reject)=>{
if(n>5){
resolve(n)
}else{
reject(n)
}
}).then((data)=>{
console.log("成功",data);
console.log(noData);
},(reason)=>{
console.log("失败",reason);
}).catch((reason)=>{
console.log(reason);
})
})
</script>
4)finally方法
无论Promise对象最后状态如何,都会执行回调函数
p.finally(()=>{
console.log("finally");
}
5)all方法、race方法
btn.addEventListener('click', () => {
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
let n = Math.ceil(Math.random() * 10)//1-10
if (n > 5) {
resolve(n)
} else {
reject(n)
}
},1000)
})
p1.then((data) => {
console.log("成功", data);
return data
}, (reason) => {
console.log("失败", reason);
return reason
},1000)
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
let n = Math.ceil(Math.random() * 10)//1-10
if (n > 5) {
resolve(n)
} else {
reject(n)
}
},2000)
})
p2.then((data) => {
console.log("成功", data);
return data
}, (reason) => {
console.log("失败", reason);
return reason
})
let p3 = new Promise((resolve, reject) => {
setTimeout(() => {
let n = Math.ceil(Math.random() * 10)//1-10
if (n > 5) {
resolve(n)
} else {
reject(n)
}
},3000)
})
p3.then((data) => {
console.log("成功", data);
return data
}, (reason) => {
console.log("失败", reason);
return reason
})
})
Promise.all()方法接受一个数组作为参数,数组中的对象都为Promise实例(如果不是promise对象,则会被用Promise.resolve转换为一个promise),数组中对象的状态决定all方法状态,数组中有一个对象的状态为失败则all方法状态为失败
Promise.all([p1, p2, p3]).then((result) => {
console.log("成功完成", result);
},(reason)=>{
console.log("部分完成",reason);
})
Promise.race(),谁先执行完谁执行race的then回调,其余将不再进入race的回调
Promise.race([p1, p2, p3]).then((result) => {
console.log("p1成功", result);
},(reason)=>{
console.log("p1失败",reason);
})
3、async/await
1)async是异步的简写,async function()用于声明一个异步函数;
await可以认为是async await的简写,用于等待一个异步方法执行完成;
async/await是一个用同步思维解决异步问题的方案(等结果出来后,代码才会继续执行)
可以通过多层async function的同步写法替代传统的callback嵌套;
2)async function
自动将常规函数转换成Promise,返回值也是一个Promise对象;
只要使用async,不管函数内部返回的是不是Promise对象,都会被包装成Promise对象
async function asfn(){
return 'async'
}
let res = asfn()
console.log(res);//Promise {[[PromiseState]]: 'fulfilled', [[PromiseResult]]: 'async'}
相当于直接通过Promise.resolve()将字符串封装为Promise对象;
函数没有返回值时,PromiseResult结果为undefined;