宏任务队列与微任务队列执行顺序例子
例如:定时器属于宏任务,Promise中then将任务加入微任务队列。
执行顺序:微任务优先级>宏任务
下面代码:
new Promise((resolve,reject)=>{
resolve(555);
console.log('Promise');
}).then(value=>console.log(result);
);
console.log(22);
由于Promise构造函数中的代码与主线程优先级相同,
先执行resolve()发送成功通知,
将then中的任务加入微任务队列,
继续执行Promise构造函数中的内容,
1.打印'Promise',然后执行下面的主线程:
2.打印 22 ,
主线程执行完毕之后,执行微任务队列中的任务:
3.打印555.
setTimeout(()=>{
console.log('setTimeout');
},0)
new Promise((resolve,reject)=>{
resolve(555);
}).then(value=>console.log(result);
);
console.log(22);
执行顺序为: 22 555 setTimeout
resolve()执行时会发送成功通知将then中的任务加入到微任务队列。
下面的执行顺序如何:
new Promise((resolve, reject) => {
setTimeout(() => {
console.log('setTimeout');//3
resolve();
}, 0);
console.log('promise');//1
}).then(function () {
console.log('成功');//4
});
console.log(22);//2
因为Promise构造函数中的执行顺序与主线程相同,
把setTimeout放入宏队列,打印promise第一个,去执行主线程,
打印22,此时resolve还在宏队列,
从宏队列中先执行setTimeOut,
然后执行resolve()执行完后发送成功通知给then,
将then中的任务加入微任务队列,最后打印 成功。
—待更新
---- Promise.all(参数为数组或具有Iterator接口)
Promise.all()用于将多个Promise实例包装成一个新的Promise实例,var p = Promise.all([p1,p2,p3]);
p的状态:
1.p1,p2,p3的状态都为Fulfilled,p的状态才会变成Fulfilled,此时p1,p2,p3的返回值组成一个数组传递给p的回调函数;
2.p1,p2,p3有一个被rejected,p就会变成rejected,此时第一个被rejected的实例的返回值会传递给p的回调函数;
---- Promise.allSettled([p1,p2,p3])与Promise.all的不同之处在于:Promise.allSettled()有出错的也会全部打印
const p1 = new Promise((resolve,reject)=>{
resolve('年龄26');
});
const p2 = new Promise((resolve,reject)=>{
reject('出错了');
})
const p3 = new Promise((resolve,reject)=>{
resolve('年龄27');
});
const p = [p1,p2,p3];
Promise.allSettled(p).then(value=>{
console.log(value);
}).catch(result=>{
console.log(result);
})
打印结果:
0: {status: “fulfilled”, value: “年龄26”}
1: {status: “rejected”, reason: “出错了”}
2: {status: “fulfilled”, value: “年龄27”}
length: 3
proto: Array(0)
此时的数据失败也返回了
可以通过数据过滤,去掉错误的数据
Promise.allSettled(p).then(values=>{
let users = values.filter(user=>{
return user.status == 'fulfilled';
})
console.log(users);
})
Promise.race()
–Promise.race([p1,p2,p3])(请求超时处理例子)
p数组中谁的状态率先改变,谁的Promise实例返回值就传递给p的回调函数。
–Promise队列的例子:
--使用Map实现Promise队列:
function queue(num) {
let promise = Promise.resolve();
num.map(v => {
promise = promise.then(() => {//上一个Promise.then的结果作为下一个promise
return new Promise(resolve => {
setTimeout(() => {
console.log(v);
resolve();
}, 1000);
})
})
})
}
queue([1, 2, 3, 4, 5]);
--Reduce封装Promise队列
function queue(num) {
num.reduce((promise, n) => {
return promise.then(() => {
return new Promise(resolve => {
setTimeout(() => {
console.log(n);
resolve();
}, 1000)
})
})
}, Promise.resolve());
}
queue([1,2,3,4,5]);
- async:相当于Promise语法糖
例一:
async function ys(){}
console.log(ys());//打印Promise状态为Resolved
例二:
async function ys(){
return ‘测试async’;
}
ys().then(v=>{
console.log(v);//打印’测试async’
})
async函数返回promise对象,await类似于then;
–下面是一个进度条加载的例子(学习视频参考):
–进度条加载:
因为没有ajax 所以直接用Promise代替。
//进度条样式
div {
width: 0px;
height: 50px;
background: green;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;//字体垂直居中
font-size: 30px;
color: #fff;
}
<div id = "loading"></div>
function query(name) {
// return ajax(`http://localhost:8080...?name=${name}`);//返回promise对象
return new Promise(resolve => {
setTimeout(() => {
resolve('qqq');
}, 1000)
})
}
async function loadUserProgress(users) {
for (let i = 0; i < users.length; i++) {
let user = await query(users[i]);
let progress = (i+1)/users.length*100;
loading.style.width = progress + '%';
loading.innerHTML = Math.round(progress) + '%';
console.log(i);
}
}
loadUserProgress(['yy', 'ys', 'xyf']);