Promise 支持链式调用解决回调函数
事件循环
js是单线程的,一次只能执行一段代码。初衷就没有考虑多线程,所以js并不具备并行任务的特性。 虽然js运行在浏览器是单线程的,但是浏览器是事件驱动的,浏览器中很多行为是异步的,会创建事件并放入执行队列中,浏览器中很多异步行为都是由浏览器新开一个线程去完成,一个线程序至少有三个常驻的线程:JS引擎线程、GUI渲染线程、事件触发线程。
运行栈(同步)
同步任务压入运行栈,按顺序依次执行
任务队列(异步)
满足可运行条件之后放入任务队列,按顺序依次执行
事件循环
会不断寻找满足运行条件的异步事件,放入任务队列中
执行顺序
- 同步
- process.nextTick
- 微任务(promise.then)
- 宏任务(计时器,ajax,读取文件)
- setImemediate
setImmediate(() => {
console.log(1)
})
console.log(2);
setTimeout(() =>{console.log(3)},0)
setTimeout(() =>{console.log(4)},100)
console.log(5);
new Promise((resolve) =>{
console.log(6)//运行栈中执行
resolve()
}).then(() =>{
console.log(7)//任务队列中执行
})
process.nextTick(() =>{
console.log(8)
})
//2,5,6,8,7,3,1,4
New promise 中的函数是同步函数
console.log(0);
return Promise.resolve(4);
}).then((res) => {
console.log(res)
})
Promise.resolve().then(() => {
console.log(1);
}).then(() => {
console.log(2);
}).then(() => {
console.log(3);
}).then(() => {
console.log(5);
}).then(() =>{
console.log(6);
})
// 大家先思考一下
Promise在项目中的一些运用
父组件
子组件
用于对外传递子组件提交数据
在父组件中利用ref调用子组件中的doSubmit方法,将子组件form中的数据return出来,到父组件统一传到后台接口中。
执行顺序
理论上宏任务会在微任务前执行,但是会发现seTimeout中的console.log却是在微任务之后输出的。 前面也写了微任务的执行顺序在宏任务之前。
这里面的原因就是在执行宏任务的时候,宏任务进入Event Table并注册函数。Event Table会将这个函数移入Event Queue。等待下一次循环的时候调用。 微任务也会进入Event Queue,但是在宏任务执行完之后Event Queue中的微任务已经在输出了。也就相当与宏任务进入Event Queue之后要等下一轮循环才会执行,但是微任务进入Event Queue会在当前循环中宏任务执行完之后就执行。所以微任务在宏任务之前输出了
setTimeout(function (){
console.log('time');
},1000)
let p = new Promise((resolve => {
console.log('p1');
resolve('p2')
}))
new Promise((resolve => {
console.log('q1');
}))
p.then((r) =>{
console.log(r);
})
// p1, q1, p2,time
- macro-task(宏任务):包括整体代码script,setTimeout,setInterval
- micro-task(微任务):Promise,process.nextTick
process.nextTick
process.nextTick 是一个独立于 eventLoop 的任务队列。
在每一个 eventLoop 阶段完成后会去检查 nextTick 队列,如果里面有任务,会让这部分任务优先于微任务执行。
let p = new Promise((resolve => {
resolve('1');
}))
async function async1() {
await async2();
let a = await p;
console.log('2')
console.log(a);
}
p.then((resolve) => {
console.log(resolve + "2");
return '3';
})
async function async2() {
console.log('4')
}
async1()
setTimeout(function () {
console.log('5')
})
// 4, 12, 2, 1, 5
async中的await后的函数可以看作为then中的函数,而await后的函数执行慢与真正的then方法。
let p = new Promise((resolve => {
console.log(1)
resolve(2);
}))
p.then((a) =>{
console.log(a);
})
async function async1() {
let a = await p;
console.log(a+'1')
}
async1();
// 1, 2, 21
then方法每一层都是一层优先级,同层先于下一层执行
let p = new Promise((resolve => {
console.log(1)
resolve(2);
}))
let q = new Promise((resolve => {
console.log(3)
resolve(4);
}))
p.then((data)=> {
console.log(5)
})
.then((data)=> {
console.log(6)
})
.then((data)=> {
console.log(10)
})
q.then((data)=> {
console.log(7)
})
.then((data)=> {
console.log(8)
})
console.log(9)
// 1,3,9,5,7,6,8,10