设为首页 加入收藏

TOP

【THE LAST TIME】彻底吃透 JavaScript 执行机制(一)
2019-09-30 16:49:17 】 浏览:79
Tags:THE LAST TIME 彻底 吃透 JavaScript 执行 机制

前言

The last time, I have learned

【THE LAST TIME】一直是我想写的一个系列,旨在厚积薄发,重温前端。

也是给自己的查缺补漏和技术分享。

欢迎大家多多评论指点吐槽。

系列文章均首发于公众号【全栈前端精选】,笔者文章集合详见Nealyang/personalBlog。目录皆为暂定

执行 & 运行

首先我们需要声明下,java script 的执行和运行是两个不同概念的,执行,一般依赖于环境,比如 node、浏览器、Ringo 等, java script 在不同环境下的执行机制可能并不相同。而今天我们要讨论的 Event Loop 就是 java script 的一种执行方式。所以下文我们还会梳理 node 的执行方式。而运行呢,是指java script 的解析引擎。这是统一的。

关于 java script

此篇文章中,这个小标题下,我们只需要牢记一句话: java script 是单线程语言 ,无论HTML5 里面 Web-Worker 还是 node 里面的cluster都是“纸老虎”,而且 cluster 还是进程管理相关。这里读者注意区分:进程和线程。

既然 java script 是单线程语言,那么就会存在一个问题,所有的代码都得一句一句的来执行。就像我们在食堂排队打饭,必须一个一个排队点菜结账。那些没有排到的,就得等着~

概念梳理

在详解执行机制之前,先梳理一下 java script 的一些基本概念,方便后面我们说到的时候大伙儿心里有个印象和大概的轮廓。

事件循环(Event Loop)

什么是 Event Loop?

其实这个概念还是比较模糊的,因为他必须得结合着运行机制来解释。

java script 有一个主线程 main thread,和调用栈 call-stack 也称之为执行栈。所有的任务都会放到调用栈中等待主线程来执行。

暂且,我们先理解为上图的大圈圈就是 Event Loop 吧!并且,这个圈圈,一直在转圈圈~ 也就是说,java scriptEvent Loop 是伴随着整个源码文件生命周期的,只要当前 java script 在运行中,内部的这个循环就会不断地循环下去,去寻找 queue 里面能执行的 task

任务队列(task queue)

task,就是任务的意思,我们这里理解为每一个语句就是一个任务

console.log(1);
console.log(2);

如上语句,其实就是就可以理解为两个 task

queue 呢,就是FIFO的队列!

所以 Task Queue 就是承载任务的队列。而 java scriptEvent Loop 就是会不断地过来找这个 queue,问有没有 task 可以运行运行。

同步任务(SyncTask)、异步任务(AsyncTask)

同步任务说白了就是主线程来执行的时候立即就能执行的代码,比如:

console.log('this is THE LAST TIME');
console.log('Nealyang');

代码在执行到上述 console 的时候,就会立即在控制台上打印相应结果。

而所谓的异步任务就是主线程执行到这个 task 的时候,“唉!你等会,我现在先不执行,等我 xxx 完了以后我再来等你执行” 注意上述我说的是等你来执行。

说白了,异步任务就是你先去执行别的 task,等我这 xxx 完之后再往 Task Queue 里面塞一个 task 的同步任务来等待被执行

setTimeout(()=>{
  console.log(2)
});
console.log(1);

如上述代码,setTimeout 就是一个异步任务,主线程去执行的时候遇到 setTimeout 发现是一个异步任务,就先注册了一个异步的回调,然后接着执行下面的语句console.log(1),等上面的异步任务等待的时间到了以后,在执行console.log(2)。具体的执行机制会在后面剖析。

  • 主线程自上而下执行所有代码
  • 同步任务直接进入到主线程被执行,而异步任务则进入到 Event Table 并注册相对应的回调函数
  • 异步任务完成后,Event Table 会将这个函数移入 Event Queue
  • 主线程任务执行完了以后,会从Event Queue中读取任务,进入到主线程去执行。
  • 循环如上

上述动作不断循环,就是我们所说的事件循环(Event Loop)。

小试牛刀

ajax({
    url:www.Nealyang.com,
    data:prams,
    success:() => {
        console.log('请求成功!');
    },
    error:()=>{
        console.log('请求失败~');
    }
})
console.log('这是一个同步任务');
  • ajax 请求首先进入到 Event Table ,分别注册了onErroronSuccess回调函数。
  • 主线程执行同步任务:console.log('这是一个同步任务');
  • 主线程任务执行完毕,看Event Queue是否有待执行的 task,这里是不断地检查,只要主线程的task queue没有任务执行了,主线程就一直在这等着
  • ajax 执行完毕,将回调函数pushEvent Queue。(步骤 3、4 没有先后顺序而言)
  • 主线程“终于”等到了Event Queue里有 task可以执行了,执行对应的回调任务。
  • 如此往复。

宏任务(MacroTask)、微任务(MicroTask)

java script 的任务不仅仅分为同步任务和异步任务,同时从另一个维度,也分为了宏任务(MacroTask)和微任务(MicroTask)。

先说说 MacroTask,所有的同步任务代码都是MacroTask(这么说其实不是很严谨,下面解释),setTimeoutsetIntervalI/OUI Rendering 等都是宏任务。

MicroTask,为什么说上述不严谨我却还是强调所有的同步任务都是 MacroTask 呢,因为我们仅仅需要记住几个 MicroTask 即可,排除法!别的都是 MacroTaskMicroTask 包括:Process.nextTickPromise.then catch finally(注意我不是说 Promise)、MutationObserver

浏览器环境下的 Event Loop

当我们梳理完哪些是 MicroTask ,除了那些别的都是 MacroTask 后,哪些是同步任务,哪些又是异步任务后,这里就应该彻底的梳理下java script 的执行机制了。

如开篇说到的,执行和运行是不同的,执行要区分环境。所以这里我们将 Event Loop 的介绍分为浏览器和 Node 两个环境下。

先放图镇楼!如果你已经理解了这张图的意思,那么恭喜你,你完全可以直接阅读 Node 环境下的 Event Loop 章节了!

setTimeout、setInterval

setTimeout

setTimeout 就是等多长时间来执行这个回调函数。setInterval 就是每隔多长时间来执行这个回调。

let startTime = new Date().getTime();

setTimeout(()=>{
  console.log(new Date().getTime()-startTime);
},1000);

如上代码,顾名思义,就是等 1s

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇jQuery中$()可以有两个参数 下一篇10 分钟上手 Vue 组件 Vue-Dragga..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目