Open logan70 opened 4 years ago
假设有以下代码,对请求结果作缓存:
let data function getData() { if (data) { console.log('loaded data') } else { ajax().then(data => { console.log('loaded data') }) } }
这样实现带来的问题是在有缓存和无缓存的情况下,执行顺序会出现不一致的情况:
console.log('get data start') getData() console.log('get data end')
上方代码在无缓存时调用,打印顺序为get data start -> get data end -> loaded data
get data start
get data end
loaded data
有缓存时调用,打印顺序为get data start -> loaded data -> get data end
如果这些打印操作变为数据修改操作,就可能导致意料之外的情况发生,所以我们可以使用微任务来确保一致的执行顺序:
function getData() { if (data) { window.queueMicrotask(() => { console.log('loaded data') }) } else { ajax().then(data => { console.log('loaded data') }) } }
这样无论有无缓存,打印顺序都为get data start -> get data end -> loaded data。
将批量操作统一处理,避免多次调用的开销。
下面的代码片段演示了如何对多个消息进行处理:通过一个微任务在当前宏任务退出时将这些消息作为单一的对象发送出去。
const messageQueue = [] let sendMessage = message => { messageQueue.push(message) if (messageQueue.length === 1) { queueMicrotask(() => { const json = JSON.stringify(messageQueue) messageQueue.length = 0 fetch('url-of-receiver', json) }) } }
上面提到的两个场景大家可能认为可以使用setTimeout替代,但有一个容易忽略的点是,假设上述任务执行时,任务队列中有宏任务等待执行,且宏任务改变了数据或阻塞线程时间过长,此时若使用setTimeout实现,可能会和预期表现有出入。
setTimeout
所以在有数据时效性要求的场景下,使用微任务可以确保当前任务执行完后执行,例如实时数据分析等。
<script>
DOM Events
I/O
requestAnimationFrame
setInterval
Promise.then
Promise.catch
Promise.finally
宏任务和微任务分别有哪些
为何区分宏任务和微任务
确保一致的执行顺序
假设有以下代码,对请求结果作缓存:
这样实现带来的问题是在有缓存和无缓存的情况下,执行顺序会出现不一致的情况:
上方代码在无缓存时调用,打印顺序为
get data start
->get data end
->loaded data
有缓存时调用,打印顺序为
get data start
->loaded data
->get data end
如果这些打印操作变为数据修改操作,就可能导致意料之外的情况发生,所以我们可以使用微任务来确保一致的执行顺序:
这样无论有无缓存,打印顺序都为
get data start
->get data end
->loaded data
。批量操作
将批量操作统一处理,避免多次调用的开销。
下面的代码片段演示了如何对多个消息进行处理:通过一个微任务在当前宏任务退出时将这些消息作为单一的对象发送出去。
时效性
上面提到的两个场景大家可能认为可以使用
setTimeout
替代,但有一个容易忽略的点是,假设上述任务执行时,任务队列中有宏任务等待执行,且宏任务改变了数据或阻塞线程时间过长,此时若使用setTimeout
实现,可能会和预期表现有出入。所以在有数据时效性要求的场景下,使用微任务可以确保当前任务执行完后执行,例如实时数据分析等。
宏任务有哪些
<script>
标签中的运行代码DOM Events
、I/O
、requestAnimationFrame
setTimeout
、setInterval
的回调函数微任务有哪些
Promise.then
、Promise.catch
、Promise.finally