美文网首页
js执行规则

js执行规则

作者: 青色琉璃 | 来源:发表于2020-04-14 16:21 被阅读0次

Q1:注册函数时会发生什么?

名字会写进event table里面

Q2:js的异步

js是一门单线程语言,全部的实现异步的方法,都是用同步去模拟的。这一点灰常重要!

Q3:事件循环Event Loop

这实际上就是js的执行机制了,也就是js实现异步的方法。

Q4:js的执行和运行

执行和运行区别很大,js在不同的环境下,如node,浏览器,Ringo等,执行方式是不同的。但是运行大多指js解析引擎,是统一的。

1,关于javascript

h5中提出了Web-Worker,但是js单线程这一点仍未改变,所谓的多线程都是用单线程模拟出来的!

2,Event Loop事件循环

js分同步任务和异步任务。

当我们打开网站时,网页的渲染过程就是一大堆同步任务,比如页面骨架和页面元素的渲染。而像加载图片音乐之类占用资源大耗时久的任务,就是异步任务。

(画图不易,且画且珍惜)


1586852433.png

如何判断主线程为空?

js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。


let data = [];

$.ajax({

    url:www.javascript.com,

    data:data,

    success:() => {

        console.log('发送成功!');

    }

})

console.log('代码执行结束');

分析:
(1) Event Table注册success函数
(2) 执行console.log('代码执行结束');
(3) ajax完成,success函数进入Event Queue
(4) 执行success函数

3,setTimeOut


function task(){

    console.log('定时器')

}

function sleep(delay) {

var start = (new Date()).getTime();

while((new Date()).getTime() - start < delay) {

    continue;

  }

}

console.log('开始')

setTimeout(() => {

    task

}, 3000)

sleep(4000);

console.log('睡眠之后')

分析:

(1)console.log('开始'),task进入Event Table

(2)执行sleep函数,主线程会卡在这儿,直到函数执行完成

(3)3秒之后,计时时间timeout结束,task进入Event Queue,但是sleep函数仍旧在执行,继续等待。

(4)4秒之后,console.log('睡眠之后');task进入主线程执行,结束。

4,setInterval

执行规则与setTimeOut类似,对于setInterval(fn,ms)来说,每隔ms时间,就会将fn推入Event Queue中,而不是每隔ms时间,就执行fn,这也意味着,如果fn的执行时间大于ms,那么就完全看不出有时间间隔了!!

5,Promise和process.nextTick(callback)

process.nextTick(callback)类似于node版的setTimeOut,在事件循环的下一次循环中调用callback。

续上回,除了广义的同步和异步任务,我们还有更精细的任务划分:

macro-task(宏任务):包括整体代码片段script,setTimeOut,setInterval

micro-task(微任务):Promise和process.nextTick

不同的任务类型会进入不同的Event Queue,比如setTimeOut,setInterval会进入相同的Event Queue。

时间循环的顺序,决定js的执行顺序。代码开始之后,从整体代码片段(宏任务)开始执行,同时将setTimeOut,setInterval中的函数置入Event Table中,随后执行微任务;下一轮开始,宏任务Event Queue开始执行,之后执行微任务。举个栗子:


setTimeout(function() {

    console.log('setTimeout');

})

new Promise(function(resolve) {

    console.log('promise');

    resolve();

}).then(function() {

    console.log('then');

})

console.log('console');

分析:

这段代码作为宏任务,进入主线程。

遇到setTimeout,将其回调函数注册后置入Event Queue。

遇到new Promise,立即执行console.log('promise')。then函数进入微任务Event Queue。

console.log('console');

第一个宏任务结束,检查微任务,执行then函数。

第一轮结束,开始第二轮。宏任务中setTimeout回调函数执行。

结束

关系图如下所示(抠图不自赏)


1586852481.png

下面,上主菜:


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')

    })

})

分析:

  • 第一轮开始,进入整体代码片段script,开始宏任务。console.log('1');

  • setTimeout,其回调函数注册,置入宏任务Event Queue,记为setTimeout1。

  • process.nextTick,其回调函数注册,置入微任务Event Queue,记为process1。

  • new Promise,立即执行console.log('7'),then函数置入微任务Event Queue,记为then1.

  • 又是一个setTimeout,其回调函数注册,置入宏任务Event Queue,记为setTimeout2。

  • 查看微任务Event Queue,发现process1和then1.

  • 执行process1,输出6

  • 执行then1,输出8

  • 第一轮输出 1,7,6,8

第二轮开始

  • 查看宏任务Event Queue,发现setTimeout1和setTimeout2.

  • 执行setTimeout1。console.log('2')。

  • process.nextTick,其回调函数注册,置入微任务Event Queue,记为process2。

  • new Promise,立即执行console.log('4');then函数置入微任务Event Queue,记为then2.

  • 宏任务结束,查看微任务,发现process2和then2。

  • 执行process2,输出3。

  • 执行then2,输出5.

第二轮输出2,4,3,5。开始第三轮

  • 执行setTimeout2。

  • console.log('9')。

  • process.nextTick,其回调函数注册,置入微任务Event Queue,记为process3。

  • new Promise,立即执行console.log('11');then函数置入微任务Event Queue,记为then3.

  • 宏任务结束,查看微任务,发现process3和then3。

  • 执行process2,输出10。

  • 执行then2,输出12.

第三轮输出9,11,10,12

三轮结束,最后输出1,7,6,8,2,4,3,5,9,11,10,12。

(请注意,node环境下的事件监听依赖libuv与前端环境不完全相同,输出顺序可能会有误差)

6,总结

微任务和宏任务还有很多种类,比如setImmediate等等,执行都是有共同点的,有兴趣的同学可以自行了解

javascript是一门单线程语言

Event Loop是javascript的执行机制

原文链接:https://juejin.im/post/59e85eebf265da430d571f89

相关文章

  • js执行规则

    Q1:注册函数时会发生什么? 名字会写进event table里面 Q2:js的异步 js是一门单线程语言,全部的...

  • Vue + Eslint + Standard + Husky

    package.json (配置依赖) .eslintrc.js (检查规则) 执行命令 VSCode插件Esli...

  • js中this问题小结

    在使用js中的this时,由于js的语法规则,this的指向是会改变的,js中的this指向是根据函数在执行时的作...

  • 宏任务与微任务

    规则 Js解析Function(整个script视为global Function)时,将同步任务排队到执行栈中,...

  • vue 安装 sass

    执行以下命令 在 build下 的 webpack.base.config.js 里的 rules 添加一条规则

  • 深入了解javascript中的this

    this 作为js中的常用引用,区别与词法作用域,有自己一套的规则 this的绑定规则 函数在执行过程中的调用位置...

  • js引擎的执行机制

    js引擎的执行机制 JS的Event Loop是JS的执行机制,理解JS的执行,必须理解Event Loop JS...

  • vue中created与mounted的区别

    浏览器渲染过程 构建DOM树 构建css规则树,根据执行顺序解析js文件。 构建渲染树Render Tree 渲染...

  • js的加载顺序

    先加载执行a.js,完毕后再加载执行b.js。 先执行a.js,完毕后再执行b.js。 这就不可以确定谁先执行了,...

  • 怎么来理解Js是单线程的这句话?

    Js是单线程指的是执行Js代码的只有Js引擎主线程。Js在js引擎中同步执行,永远都是运行执行栈最顶部的代码。那么...

网友评论

      本文标题:js执行规则

      本文链接:https://www.haomeiwen.com/subject/ntetvhtx.html