Javascript异步原理是JavaScript的一大特性,能够让多个用户输入在后台同时执行,从而带来流畅的界面交互。但是JavaScript的异步原理的背后却有许多复杂的过程值得我们探究。
首先,所谓“异步”,简单说就是一个任务分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段。而常见的浏览器无响应(假死),往往就是因为某一段 Javascript 代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。为了解决这个问题,Javascript 语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。
JavaScript 引擎负责解析,执行JavaScript代码,但它并不能单独运行,通常都得有一个宿主环境,一般如浏览器或 Node 服务器,前文说到的单线程是指在这些宿主环境创建单一线程,提供一种机制,调用 JavaScript 引擎完成多个JavaScript 代码块的调度,这种机制就称为事件循环(Event Loop)。
很多的队列先后按顺序执行任务就形成了事件。
笼统地说,异步在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前端知识在等你攫取!
代码小兵49806-11 15:28
代码小兵49806-11 15:51
代码小兵49806-11 16:22
代码小兵51603-29 17:28
暴风城-小飞04-06 20:49