JS同步与异步

一、JavaScript

 

我们常说“JavaScript是单线程的”。

所谓单线程,是指在JS引擎中负责解释和执行JavaScript代码的线程只有一个。可以叫它主线程

 

二、同步和异步

同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;

异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

异步请求执行过程:

主线程发起一个异步请求,相应的工作线程接收请求并告知主线程已收到(异步函数返回);主线程可以继续执行后面的代码,同时工作线程执行异步任务;工作线程完成工作后,通知主线程;主线程收到通知后,执行一定的动作(调用回调函数)。

(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。

(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。

(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。

(4)主线程不断重复上面的第三步。

 

例如ajax执行过程

 

let data = [];
$.ajax({
    url:www.javascript.com,
    data:data,
    success:() => {
        console.log('发送成功!');
    }
})
console.log('代码执行结束');

 

  • ajax进入Event Table,注册回调函数success
  • 执行console.log('代码执行结束')
  • ajax事件完成,回调函数success进入任务队列。
  • 主线程从任务队列读取回调函数success并执行。

 

 

"任务队列"是一个事件的队列(也可以理解成消息的队列),IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈"了。主线程读取"任务队列",就是读取里面有哪些事件。

"任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程读取。

所谓"回调函数"(callback),就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。

 

三、setTimeout执行机制

由于JavaScript引擎同一时间只执行一条代码(这是由于JavaScript单线程的性质),所以每一个JavaScript代码执行块会 “阻塞”其它异步事件的执行。这就意味着当一个异步事件发生(例如,鼠标点击,计时器被触发,或者Ajax异步请求)后,这些事件的回调函数将排在执行队 列的最后等待执行

// some code

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

// some code

document.getElementById('btn').click();

// some code

setInterval(function() {
  console.log('world');
}, 10);

// some code

 

我们开始执行代码。第一块代码大概执行了18ms,也就是JavaScript的主体代码,在执行过程中,先触发了一个setTimeout函数,代码继续执行,只等10ms后响应setTimeout的回调,接着是一个鼠标点击事件,该事件有个回调(或许是alert一些东西),不能立即执行(单线程),因为js主体代码还没执行完,所以这个回调被插入执行队列中,等待执行;接着setInterval函数被执行,我们知道,此后每隔10ms都会有回调(尝试)插入队列中,运行到第10ms的时候,setTimeout函数的回调插入队列。js函数主体运行完后,大概是18ms这个点,我们发现队列中有个click的callback,还有个setTimeout的callback,于是我们先运行前者,在运行的过程中,setInterval的10ms响应时间也过了,同样回调被插入队列。click的回调运行完,运行setTimeout的回调,这时又10ms过去了,setInterval又产生了回调,但是这个回调被抛弃了,之后发生的事大家都一目了然了。

 

posted @ 2018-10-24 12:27  LFei_0619  阅读(142)  评论(0)    收藏  举报