共计 1142 个字符,预计需要花费 3 分钟才能阅读完成。
JS是单线程
JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事
这是因为 Javascript 这门脚本语言诞生的使命所致————JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生
的
比如我们对某个 DOM 元愫进行添加和删除操作,不能同时进行,应该先进行添加,之后再删除
单线程就意味着,所有的任务需要排队,前一个任务结束,才会执行后一个任务
这样所导致的问题是:如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉
同步和异步
为了解决上面的问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程
于是 JS 中出现了同步和异步
同步
前一个任务结束后在执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的
比如做饭的同步做法:我们要烧水煮饭,等水开了(5分钟之后),才能去切菜,炒菜
异步
你在做一件事情时,因为这件事情会花费很长时间,在做这件事情的同时,你还可以去处理其他事情
比如做饭的异步做法:我们在烧水的同时,利用这10分钟,去切菜,炒菜
同步任务
同步任务都在主线程上执行,形成一个执行栈
异步任务
JS 的异步任务是通过回调函数实现的,一般而言,异步任务有以下三种类型:
- 普通事件,如
click
、resize
等 - 资源加载,如
load
、error
等 - 定时器,包括
serInterval
、setTimeot
等
异步任务相关回调函数添加到任务队列中(任务队列也称消息队列)
执行过程
- 先执行执行栈中的同步任务
- 异步任务(回调函数)放入任务队列中
- 一旦执行栈中所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,放入执行栈,开始执行
执行机制
由于主线程不断重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为 事件循环(event loop)
如何理解 JS 的异步
JS 是一门单线程的语言,这是因为它运行在浏览器的渲染主线程中,而渲染主线程只有一个。而且渲染主线程承担着诸多的工作,渲染页面、执行 JS 代码,都在其中运行。
如果使用同步的方式,就极有可能导致主线程产生堵塞,从而导致消息队列中的很多其他任务无法得到执行。这样一来,一方面会导致繁忙的主线程白白的消耗时间,另一方面导致页面无法及时更新,给用户造成卡死现象。
所以浏览器采用异步的方式来避免。具体的做法就是当某些任务发生时,比如计时器、网络请求、事件监听,主线程将任务交给其他的线程去处理,自身立即结算任务的执行,转而执行后续的代码。当其他线程完成时,将事先传递的回调函数包装成任务,加入到消息队列的末尾排队,等待主线程调度执行。
在这种异步模式下,浏览器永不阻塞,从而最大限度的保证了单线程的流畅运行。