引言
在前端开发中不免使用到nextTick,它是如何实现的呢?什么是eventloop呢?它可是无处不在,如果你对它不是很了解,那么有些逻辑可能会屡屡报错,因为它涉及到代码的执行顺序问题,下面来详细了解一下。
正文
js
是单线程的,如果某段程序需要等待一会再执行,后面的程序会被阻塞,这样也就带来了一些问题。为了解决这些问题,js
出现了同步和异步两种任务,两种任务的差异就在于执行的优先级不同。eventloop
就是对任务的执行顺序做了详细的规范。
异步任务
异步任务分为宏任务和微任务
常见的宏任务有:setTimeout、setInterval
、setImmediate(node环境)
、xhr
,callback
常见的微任务有:Promise.then()、finally、catch
、process.nextTick
需要注意Promise本身是同步任务,.then和.catch才是微任务。例如:
new Promise((resove,reject)=>{
console.log(1) //同步任务
resove(3)
}).then((res)=>{
console.log(res) //异步任务(微任务)
})
输出结果:1 3
执行顺序
同步任务 ——> 微任务 ——> 宏任务
无论同步或异步任务,都在主线程执行,怎么在主线程进行这些不同任务之间的执行呢?
这就需要用到eventloop(事件循环)
:
任务在主线程不断进栈出栈的一个循环过程,会在将要执行时进入主线程,在执行完毕后会退出主线程。
把同步任务放入主线程,同步任务执行完毕就退出主线程,接着把微任务放主线程,执行完毕退出主线程,最后是宏任务。
nextTick详解
nextTick
就是创建一个异步任务。
源码(地址core\packages\runtime-core\src\scheduler.ts):
const resolvedPromise: Promise<any> = Promise.resolve()
let currentFlushPromise: Promise<void> | null = null
export function nextTick<T = void>(
this: T,
fn?: (this: T) => void
): Promise<void> {
const p = currentFlushPromise || resolvedPromise
return fn ? p.then(this ? fn.bind(this) : fn) : p
}
nextTick接收一个fn参数,并定义了一个变量p,单看变量p始终是一个Promise。最后return 如果传了fn就使用变量p.then执行一个微任务去执行fn函数,then里面this 如果有值就调用bind改变this指向返回新的函数,否则直接调用fn,如果没传fn,就返回一个promise,最终结果都会返回一个Promise。