1.对于javascript


   javascript是一门单线程语言,在最新的HTML5中提出了Web-Worker,但javascript是单线程这一外围仍未扭转。所以所有javascript版的"多线程"都是用单线程模仿进去的,所有javascript多线程都是纸老虎!(不论是什么新框架新语法糖实现的所谓异步,其实都是用同步的办法去模仿的)

2.javascript事件循环

事件循环是js实现异步的一种办法,也是js的执行机制。首先浏览器会把主工作队列中的同步工作挨个全副执行完,而后再去期待工作队列中看哪个工作能够执行了,而后把该执行的工作放到主工作队列中去执行,等这个工作执行完,再去期待工作中看谁能够执行了,再把这个工作放到主工作队列中执行... 如此循环。这种循环叫做事件循环(Event Loop)

js是单线程,js工作也要一个一个程序执行。如果一个工作耗时过长,那么后一个工作也必须等着。那么问题来了,如果咱们想浏览新闻,然而新闻蕴含的超清图片加载很慢,难道咱们的网页要始终卡着直到图片齐全显示进去?因而聪慧的程序员将工作分为两类:1)同步工作 2)异步工作

一张图示意事件循环
#1.同步和异步工作别离进入不同的执行"场合",同步的进入主线程,异步的进入Event Table并注册函数。#2.当指定的事件实现时,Event Table会将这个函数移入Event Queue。#3.主线程内的工作执行结束为空,会去Event Queue读取对应的函数,进入主线程执行。#4.上述过程会一直反复,也就是常说的Event Loop(事件循环)。主线程执行栈何时为空?js引擎存在monitoring process过程,会继续一直的查看主线程执行栈是否为空,一旦为空,就会去Event Queue那里查看是否有期待被调用的函数。~~~~

所以能够看做是这样的:
1.浏览器线程先执行同步工作,途中遇到异步工作就将其退出到期待工作队列中去,而后持续向下执行,
2.等同步工作全副执行结束后,再去期待工作队列中去将所有可执行的微工作一一执行,
3.执行完微工作后在拿取第一个先达到执行条件的宏工作来执行,
4.执行完后再去期待工作队列中清理执行完所有已达到执行条件的微工作,
5.而后再拿取下一个宏工作来执行,如果宏工作执行产生微工作或者微工作执行产生宏工作就一样退出到期待工作队列中,而后还是依照主线程每次到期待队列中先执行完所以的微工作再一一执行宏工作的程序来走

异步工作都是谁先达到条件谁先执行,然而谁先达到执行条件也有优先级的问题,这个优先级要看这个工作是宏工作还是微工作;微工作的优先级比宏工作的要高;

3.运行机制

在事件循环中,每进行一次循环操作称为 tick,每一次 tick 的工作解决模型是比较复杂的,但关键步骤如下:

*     执行一个宏工作(栈中没有就从事件队列中获取)*     执行过程中如果遇到微工作,就将它增加到微工作的工作队列中*     宏工作执行结束后,立刻执行以后微工作队列中的所有微工作(顺次执行)*     以后宏工作执行结束,开始查看渲染,而后GUI线程接管渲染*     渲染结束后,JS线程持续接管,开始下一个宏工作(从事件队列中获取)
一张图解释
宏工作:
(macro)task,能够了解是每次执行栈执行的代码就是一个宏工作(包含每次从事件队列中获取一个事件回调并放到执行栈中执行)。浏览器为了可能使得JS外部(macro)task与DOM工作可能有序的执行,会在一个(macro)task执行完结后,在下一个(macro)task 执行开始前,对页面进行从新渲染,流程如下:(macro)task->渲染->(macro)task->...
微工作:
microtask,能够了解是在以后 task 执行完结后立刻执行的工作。也就是说,在以后task工作后,下一个task之前,在渲染之前。所以它的响应速度相比setTimeout(setTimeout是task)会更快,因为无需等渲染。也就是说,在某一个macrotask执行完后,就会将在它执行期间产生的所有microtask都执行结束(在渲染前)。
宏工作(macrotask)微工作(microtask)
谁发动的宿主(Node、浏览器)JS引擎
具体事件1.script(同步代码), 2.setTimeout/setInterval, 3.UI rendering/UI事件, 4.postMessage,MessageChannel, 5.setImmediate,I/O(Node.js)1. Promise, 2.MutaionObserver, 3.Object.observe(已废除;Proxy 对象代替), 4.process.nextTick(Node.js)
谁先运行后运行先运行
会触发新一轮tick吗不会
代码块1
setTimeout(function(){console.log('1')});new  Promise(function(resolve){  console.log('2');  resolve();}).then(function(){console.log('3')});console.log('4');//2  4  3  1

剖析:
(1)settimeout是宏工作,尽管先执行的他,然而他被放到了宏工作的eventqueue外面,(2)往下查看看有没有微工作,发现Promise回调函数内的代码是同步的(微工作)输入2
(3)then函数把他放入了微工作序列。
(4)主代码块(宏工作)输入4
(5)主线过程所有代码执行完结。先从微工作queue里拿回掉函数,输入3微工作全副实现
(6)再从宏工作的queue拿函数。输入1

代码块2
console.log('1');setTimeout(function() {    console.log('2');    process.nextTick(function() {        console.log('3');    })    new Promise(function(resolve) {        console.log('4');        resolve();    }).then(function() {        console.log('5')    })})process.nextTick(function() {    console.log('6');})new Promise(function(resolve) {    console.log('7');    resolve();}).then(function() {    console.log('8')})setTimeout(function() {    console.log('9');    process.nextTick(function() {        console.log('10');    })    new Promise(function(resolve) {        console.log('11');        resolve();    }).then(function() {        console.log('12')    })})

1.主代码块输入1
2.宏工作1setTimeout(2,3,4,5)
3.微工作1process(6)
4.promise立刻执行,回调是同步输入7,then微工作2(8)
5.宏工作2setTimeout(9,10,11,12)
主代码全副执行完(余微工作1,2,宏工作1,2)
6.执行微工作1,输入6
7.执行微工作2,输入8
微工作全副执行完(余宏工作1, 2)
8.执行宏工作1,输入2,
增微工作process(3)
promise立刻执行回调输入4,微工作(5),
9.执行微工作输入3,输入5
10.执行宏工作2,输入9,
增微工作process(10)
promise立刻执行回调输入11,微工作(12),
11.执行微工作输入10,输入12

代码块3
async function async1() {    console.log('async1 start');    await async2();    console.log('async1 end');}async function async2() {    console.log('async2');}console.log('script start');setTimeout(function() {    console.log('setTimeout');}, 0)async1();new Promise(function(resolve) {    console.log('promise1');    resolve();}).then(function() {    console.log('promise2');});console.log('script end');

1.输入“script start”
2.setTimeout宏工作
3.执行async1()输入async1 start,执行 async2(),输入 “async2”。
4.async2执行结束,将await async2 前面的代码退出到 微工作队列async1 end');
5、继续执行,new Promise, 同步输入“promise1”。promise.then,退出到微工作队列,
6.输入script end
7.以后宏工作执行结束,查看微工作队列输入async1 end “promise2”
8.微工作全副执行完,查看宏工作,输入setTimeout

改下面代码:

async function async1() {    console.log('async1 start');    let p = await async2();    console.log(p);    console.log('async1 end');}async function async2() {    console.log('async2');    return new Promise(((resolve, reject) => {        resolve(10);    }))}console.log('script start');setTimeout(function() {    console.log('setTimeout');}, 0)async1();new Promise(function(resolve) {    console.log('promise1');    resolve();}).then(function() {    console.log('promise2');});console.log('script end');script startasync1 startasync2promise1script endpromise210 async1 endsetTimeout
new promise的操作就跟你 new 一个一般函数没区别,所以这一句其实是宏工作,但前面的then是微工作
resolved后的promise对象会在这该级别事件队列完结之后才开始执行,及执行与该轮微工作队列中,始于下一级别宏工作之前
resolved 的 Promise 是在本轮事件循环的开端执行,总是晚于本轮循环的同步工作。

如果呈现两个这种微工作,则先呈现的会先执行

async 函数中,遇到 await 会跳出以后函数,并让出线程,再将await前面的代码放到 微工作(microtask)队列中