Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

并发模型与事件循环 #16

Open
gaofant101 opened this issue Jan 4, 2018 · 1 comment
Open

并发模型与事件循环 #16

gaofant101 opened this issue Jan 4, 2018 · 1 comment

Comments

@gaofant101
Copy link
Owner

gaofant101 commented Jan 4, 2018

@ 并发模型与事件循环

可视化描述

javascript 运行时, 主线程产生堆(heap)、 栈(stack)、消息队列(queue);

  • 堆(heap): 对象被分配在一个堆中, 即用以表示一个大部分非结构化的内存区域;
  • 栈(stack): 函数调用形成一个栈帧;
  • 队列(queue): 一个 javascript 运行时包含了一个待处理的消息队列. 每一个消息都与一个函数相关联. 当栈拥有足够内存时, 从队列中取出一个消息进行处理. 这个处理过程包含了调用与这个消息相关联的函数(以及因而创建了一个初始堆栈帧). 当栈再次为空的时候, 也就意味着消息处理结束;

体现

task-queue

macrotasks: setTimeout setInterval setImmediate I/O UI rendering
microtasks: Promise process.nextTick Object.observe MutationObserver

例子

我们直接用例子来看看 tasks 运行流程, 默记一下打印的内容顺序是什么.

console.log('script start');

setTimeout(function() {
    console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
    console.log('promise1');
}).then(function() {
    console.log('promise2');
});

console.log('script end');

过程

  1. 开始运行 javascript, 引擎主线程运行, 产生栈(stack);

  2. 从上往下执行同步代码, lgo(script start) 压入执行栈(stack), log 是浏览器内方法不属于webapi, 立即出栈(stack)执行, 打印script start;

  3. 往下执行, 遇到 settimeout 异步任务, 压入执行栈(stack), 查看任务类型, 分配到tasks queue;

  4. 往下执行, 遇到 promise 异步任务, 压入执行栈(stack), 查看任务类型, 分配到 microtasks queue;

  5. 往下执行, 同步骤 (2), 压入执行栈(stack), 立即出栈(stack)执行, 打印script end;

  6. 这个时候task queue空闲, 开始轮询(even loop) 查看栈(stack)积情况, task 执行过 log; 开始提取 microtasks queue;

  7. 执行 promise then, promise callback 压入栈(stack), 出栈执行promise callback , 打印 promise1, promise callback returns undefined;

  8. 继续执行 promise then 又一个异步任务, 添加到 microtasks queue;

  9. 第一个microtask 执行完毕, 执行下一个 microtask;

  10. 同步骤(7), promise callback 压入栈(stack), 出栈执行 promise callback , 打印 promise2 ;

  11. 到这里 microtask 全部执行完毕, 浏览器可能 update rendering;

  12. 继续轮询even loop, 查看栈(stack)积情况, 调取tasksetTimeout callback出栈执行; 打印 setTimeout;

  13. 到此所有的task执行完毕; 任务列队处于空闲状态;

过程图解

Queue<1>

Queue<2>

Queue<3>

Queue<4>

Queue<5>

Queue<6>

Queue<7>

Queue<8>

Queue<9>

Queue<10>

Queue<11>

Queue<12>

Queue<13>

Queue<14>

Queue<15>

Queue<16>

Queue<17>

Queue<18>

Queue<19>

Queue<20>

结果以chrome为基准; 在firefoxsafariwindows browser中可能不一样;
差异化可以查看Jake Archibald blog

Even Loop

@ 参考

并发模型与事件循环

tasks-microtasks-queues-and-schedules

event-loop-timers-and-nexttick

MutationObserver

@gaofant101 gaofant101 changed the title 并发模型与事件循环.md 并发模型与事件循环 Jan 4, 2018
@wuyxp
Copy link

wuyxp commented Jan 4, 2018

大神

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants