promise的出现解决了ajax的回调地狱问题,同时增加了代码的可读性和可维护性
三种状态:
1.pending[待定]初始状态
2.fulfilled[实现]操作成功
3.rejected[拒绝]操作失败
var promise = new Promise(传一个函数);
var promise = new Promise( function (resolve, reject){
if(/*异步操作成功*/){
resolve(valve); //resolve返回一个给定的值的promise对象,也就是说下面res参数的值是value
}else{
reject(error); //返回一个带有拒绝原因的Promise对象,也就是说下面err的值是error
}
});
promise.then(res =>{
console.log(res); //成功resolve('success')
}).catch(err=>{
console.log(err);
})
Promise.all
Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组(要全部成功才会返回),失败的时候返回的是最先被reject失败状态的值
let p1 = new Promise((resolve,reject) => {
resolve('成功了')
})
let p2 = new Promise((resolve,reject) => {
resolve('success')
})
let p3 = Promise.reject('失败')
Promise.all([p1, p2]).then((result) => {
console.log(result) //['成功', 'success']
}).catch((error)=>{
console(error)
})
Promise.all([p1,p2,p3]).then((result) => {
console.log(result)
}).catch(error => {
console.log(error) //失败了,打印“失败”
})
Promise.race
Promise.race就是赛跑的意思,就是说Promise.race([p1, p2, p3])里面哪个结果获得得快,就返回那个结果,不管该结果是成功还是失败状态
let p1 = new Promise((resolve, reject) =>{
setTimeout(()=>{
resolve('success')
},1000)
})
let p1 = new Promise((resolve, reject) =>{
setTimeout(()=>{
reject('failed')
},500)
})
Promise.race([p1, p2]).then((result) =>{
console.log(result)
})catch((error) =>{
console.log(error) //打开的是'failed'
})
Async/await
也是用来处理异步的,其实是Generator函数的改进,背后原理就是promise
- await后面接一个会return new promise的函数并执行它
- await只能放在async函数里
情况1:
async function f1() {
return "abc";
//自动包装成promise对象
//与下面两种等价
//return Promise.resolve('abc');
//return new Promise((resolve) => { resolve('abc') });
}
console.log(f1()) //函数会返回一个Promise对象
情况2:
async function f3(){
return 'f3';
}
function f4(){
return 'f4';
}
async function(){
var c = await f3(); //等待f3执行完毕才执行这里的代码
var d = await f4();
console.log(c,d);
//看到await,会阻塞后面的代码,等于程序执行完,再回来执行
}
Promise和setTimeout,宏任务和微任务的问题
setTimeout(function(){console.log(1)},0);
new Promise(function(resolve){
console.log(2)
for( var i=0 ; i<10000 ; i++ ){
i==9999 && resolve()
}
console.log(3)
}).then(function(){
console.log(4)
});
console.log(5);
// 这的问题是,为什么答案是 2 3 5 4 1
// 而不是 2 3 5 1 4
参考https://blog.csdn.net/xiaojinguniang/article/details/88311534
在执行这段代码时,主程序是第一个宏任务,setTimeout是第二个宏任务,promise内是同步执行的,而promise的回调是异步执行的微任务。
每一个宏任务执行完毕都必须将当前的微任务队列清空
我们来捋一遍代码的执行过程,
所有的代码都写在script标签中,所以读取所有代码是第一个宏任务,我们开始执行第一个宏任务。
我们首先遇到setTimeout,他是第二个宏任务,将它扔进宏任务事件队列里先排队。
下来我们遇到promise,promise执行器里的代码会被同步调用,所以我们依次打印出2和3。
下来遇到promise的回调,他是一个微任务,将它扔进微任务事件对列中。
下来我们接着打印出5,然后执行微任务并且打印出4.
我们第一个宏任务执行完毕,执行下一个宏任务,打印出1,到此,所有任务都执行完毕。
所以我们最后的结果为2 3 5 4 1