动力节点首页 全国咨询热线:400-8080-105

绑定手机号,登录
手机号

验证码

微信登录
手机号登录
手机号

验证码

微信登录与注册
微信扫码登录与注册

扫码关注微信公众号完成登录与注册
手机号登录
首页 > 文章

浅析Javascript异步原理

04-28 10:32 726浏览
举报 T字号
  • 大字
  • 中字
  • 小字

Javascript异步原理是JavaScript的一大特性,能够让多个用户输入在后台同时执行,从而带来流畅的界面交互。但是JavaScript的异步原理的背后却有许多复杂的过程值得我们探究。

首先,所谓“异步”,简单说就是一个任务分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段。而常见的浏览器无响应(假死),往往就是因为某一段 Javascript 代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。为了解决这个问题,Javascript 语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。

JavaScript 引擎负责解析,执行JavaScript代码,但它并不能单独运行,通常都得有一个宿主环境,一般如浏览器或 Node 服务器,前文说到的单线程是指在这些宿主环境创建单一线程,提供一种机制,调用 JavaScript 引擎完成多个JavaScript 代码块的调度,这种机制就称为事件循环(Event Loop)。

  • 宿主环境为JavaScript 创建线程时,会创建堆 (heap) 和栈 (stack) ,堆内存储 JavaScript 对象,栈内存储执行上下文;
  • 栈内执行上下文的同步任务按序执行,执行完即退栈,而当异步任务执行时,该异步任务进入等待状态(不入栈),同时通知线程:当触发该事件时(或该异步操作响应返回时),需向消息队列插入一个事件消息;
  • 当事件触发或响应返回时,线程向消息队列插入该事件消息(包含事件及回调);
  • 当栈内同步任务执行完毕后,线程从消息队列取出一个事件消息,其对应异步任务(函数)入栈,执行回调函数,如果未绑定回调,这个消息会被丢弃,执行完任务后退栈;
  • 当线程空闲(即执行栈清空)时继续拉取消息队列下一轮消息(next tick ,事件循环流转一次称为一次 tick )。

很多的队列先后按顺序执行任务就形成了事件。

笼统地说,异步在javascript就是延时执行。严格来说,javascript中的异步编程能力都是由BOM与DOM提供的,如setTimeout,XMLHttpRequest,还有DOM的事件机制,还有HTML5新增加的webwork, postMessage,等等很多。这些东西都有一个共同的特点,就是拥有一个回调函数,实现控制反转。回调函数的存在打断了原来的执行流程,让它们自行在适当的时机出现并执行,这是个非常便捷的模式。对比主动式的轮询,很明显它的节能性更好。

我们知道JS引擎就是以单线程的机制来运行代码。那么在JS代码中想要实现异步就只有采用单线程非阻塞式的方式。比如下面这段代码:

console.log("start");
setTimeout(function(){
    console.log("timeout");
},5000);
console.log("end");
这段代码先输出一个字符串”start”,然后用时间延迟函数,等到5000秒钟后输出”timeout”,在代码的最后输出”end”。最后的执行结果是:
start
end
//等待5秒后
timeout

从结果可以看到end的输出并没有等待时间函数执行完,实际上setTimeout就是异步的实现。代码的执行流程是这样的:

首先执行输出字符串”start”,然后开始执行setTimeout函数。由于它是一个异步操作,所以它会被分为两部分来执行,先调用setTimeout方法,然后把要执行的函数放到一个队列中。代码继续往下执行,当把所有的代码都执行完后,放到队列中的函数才会被执行。这样,所有异步执行的函数都不会阻塞其他代码的执行。虽然,这些代码都不是同时执行,但是由于任何代码都不会被阻塞,所以执行效率会很快。

在同步编程,代码基本上自上向下执行,在异步编程,一些代码就要写到回调函数中,如果代码之间存在依赖,回调函数套回调函数的情况也不少见,这种套嵌结构对以后的维护来说简直是地狱。还有一种我们不得不面对的情况,try...catch无法捕捉几毫秒之后发生的异常。另外,除了setTimeout外,异步编程基本上由事件机制承担的,它们的回调函数什么时候发生基本上都是未知数,可能由于后台发生系统级错误,无法再发出响应,或者,系统忙碌,一时半刻响应不过来,这两种情况我们也必需提供一个策略,中断这操作,也就是所谓的abort,这些都是异步编程的所要处理的课题。

当你访问服务器的时候,比如请求一个html页面,比如用户列表。服务器一方面会去读取模板文件,可能是ejs、pug、jade、handlebar、另外一方面还要读取数据(可能会放在文件里,也可以会放在数据里),它们都很慢,所以都是异步的.

可以说JavaScript的异步原理是整个JavaScript处理线程冲突的核心机制,避免了JavaScript 的单线程执行环境带来的弊端。想要学习更多的JavaScript的知识可以观看动力节点在线的JavaScript专题课程,更多JavaScript前端知识在等你攫取!

0人推荐
共同学习,写下你的评论
0条评论
代码小兵498
程序员代码小兵498

153篇文章贡献528999字

相关课程 更多>

作者相关文章更多>

推荐相关文章更多>

JavaWeb的3大组件

代码小兵49806-11 15:28

全面解析Cookie技术

代码小兵49806-11 15:51

浅谈JavaWeb架构演变

代码小兵49806-11 16:22

探讨Web开发中的Session存储与管理

代码小兵51603-29 17:28

JavaScript基础知识

 暴风城-小飞04-06 20:49

发评论

举报

0/150

取消