Javascript中的异步

Web项目聚集地

前沿技术交流,资源分享

公众号内回复:全栈

?全栈资源?

前言

博客地址:www.illgo.cn

在Javascript这样类型的语言中编程最重要但最常被人误解的部分之一,就是如何控制在一段时间内程序的行为次序.同时,JavaScript中的异步,也经常被人和并行搞混.今天,我们来谈一下JavaScript中的异步. 自JS开始以来,异步编程一直存在.然而,但是大多数JS开发人员从未真正仔细考虑过在程序中如何以及为何出现问题,也没有去探索各种其他处理方法。 比较好的方法一直是稀里糊涂的使用回调函数.到今天为止,许多人会坚持认为回调使用起来就已经绰绰有余了.

什么是异步?

首先,一段JavaScript程序是由多个块(chunk)组成的,最常见的块就是function–函数. 我们把一段时间内,程序要执行的任务分为两部分: 1.执行部分(现在执行的),2.等待部分(剩下的将来要执行的).而我们面临的问题是,当现在执行部分执行完后,程序并不是严格地立马去完成等待部分.换句话就是,这些块是异步执行的.我们不会像预期的那样阻塞地完成一个接一个的任务.

例如:

//ajax是某些JavaScript框架(如:jQurey)中实现Ajax的函数let data = ajax( "http://some.url.1" );
//控制台输出data内容console.log(data)

如果运行这段JavaScript代码会发现,打印出来的data通常没有我们想要的ajax请求结果. 这是因为,Ajax请求并不是同步(synchronously,相对于异步asynchronously)完成的,当执行console.log()的时候,我们想要的data还没有返回.我们想要的其实是ajax(...)函数能够阻塞,一直到请求结果返回,最简单的解决方法就是回调(callback).

//回调方式的一个示例,具体回调方式根据具体来定.ajax( "http://some.url.1", function myCallbackFunction(data){
	console.log( data );
} );

这时我们会发现,data就是我们想要的了. 注意:我们是可以同步地请求Ajax的,比如:jQurey中的ajax()async: false加入设置.但是这样做的后果就是浏览器的UI操作(按钮,滚动等)以及用户交互等都会被阻塞等待锁死.我们应该避免这种情况,一团乱麻的回调函数也不应成为使用同步Ajax的理由.

记下来我们再考虑另一个例子帮助理解:

function now() {	return 21;}
function later() {	answer = answer * 2;	console.log( "answer:", answer );}
var answer = now();
setTimeout( later, 1000 ); // answer: 42

我们再用刚才的思路去理解这个程序:分为两个部分:执行部分,等待部分.

执行部分是:

//回调方式的一个示例,具体回调方式根据具体来定.ajax( "http://some.url.1", function myCallbackFunction(data){
	console.log( data );
} );

等待部分就是later()中的内容:

answer = answer * 2;console.log( "answer:", answer );

执行部分会立刻执行,而setTimeout(...)会设定一个事件(timeout事件),在1000ms后执行later().就像这样,每当我们在function中写一段代码,并让它在事件(timer,鼠标事件,Ajax响应等)响应后执行,我们就创造了一个等待部分,也就是在程序中使用了异步.

Event Loop

虽然我们在这里谈异步,但是,直到ES6*,JavaScript本身并没有内置异步的概念.听起来很震惊,但事实确实是这样的.我们会问:那我们讨论的异步是怎么实现的呢?? 我们都知道的是JavaScript引擎从来不是独立执行,总要依赖于一个环境,比如,我们最熟悉的web浏览器.以及服务器上的Node.js.这些环境会用一个机制来随时间使用JavaScript引擎处理我们的多个程序块,这个机制我们管它叫Event Loop. 换句话说,JavaScript引擎并不知道什么时候执行,而是被执行环境的线程来安排处理哪些程序块,执行环境根据事件来调度JavaScript引擎处理. 那么什么是Event Loop呢? 我们通过一段伪代码来了解它的概念:

//eventLoop是事件排成的先进先出的队列(queue)var eventLoop = [ ];var event;
while(true) {	// 处理完一个事件	if (eventLoop.length > 0) {		// 获取队列中的下个动作		event = eventLoop.shift();
		// 处理刚才取出的动作		try {			event();		}		catch (err) {			reportError(err);		}	}}

我们通过这段伪代码大体了解它的机制.我们有一个循环,循环的每一个迭代中,如果在等待队列中存在事件,就会被取出并处理,event()就是各种回调函数. 因此,到这儿我们就可以明白了,setTimeout(..)不是把设定好的回调函数安排到event loop中,而是将一个计时器(timer)安排在event loop中,当计时器到期,执行环境将回调推入event loop,这样,在将来某个时间会被取出并执行. 假如,现在event loop中已经存在20个等待的成员,那么这个回调就应该等待,通常没有方法能将他移动到队列头部,让他立马执行.这样就产生了,哪怕用了setTimeout(..),指定的回调并不会在指定时间后立即执行的现象,当然也不会提前,至于是否要等待,等待多久,要根据具体情况来说.

注意:之所以说是”直到ES6”,是因为ES6引入了Promise机制,ES6通过Promise将event loop的工作机制纳入到了JavaScript引擎的工作范围,而不只是执行环境的工作.关于Promise以后有机会再谈.

并行

有一个常见的现象就是,人们经常把”异步”和”并行”混为一谈,其实他们大不相同.”异步”,指的是执行部分和等待部分中间有时间差,并不是立即执行.而并行则是指一起执行. 并行计算中最常见的单位是进程(process)和线程(thread),进程和线程之间可以是独立执行,也可以在一个处理器中,或者一台电脑中同时执行.通常,多个线程可以共享单个进程的内存. 相比之下,event loop是将一个工作分解成多个任务,并组成队列串行执行,不能并行访问和更改共享的内存.它的并行性和”串行性”可以在不同线程下的event loop上体现(一个线程可以创立一个event loop,不同线程下的event loop具有并行性,单个event loop具有串行性). 并行地执行线程和异步地交错处理事件在粒度级别上有着很大的不同.线程是表达式操作级别,而异步是函数级别。

如有收获,请打赏作者

作者:Illgo

博客地址:www.illgo.cn

通知:欢迎大家踊跃投稿,打赏归你哦!

—— End ——

原文发布于微信公众号 - Web项目聚集地(web_resource)

原文发表时间:2018-04-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏烙馅饼喽的技术分享

我的CMS开发记-4 介绍一下DotNetNuke的系统执行流程

       有朋友说应该写个大致结构出来。想想也有道理,那么我就来介绍一下Dotnetnuke的执行流程。基本上我这个就是照搬他的 基本思路     一个站点...

3318
来自专栏zhisheng

0Day技术分析-1-基础知识

1 基础知识 本章介绍一些与0Day相关的基本概念及基础知识。 1.1. Bug与漏洞 有一个比较有趣的事件,话说某个软件中存在99个Bug,某一天研发人员心血...

3134
来自专栏有趣的Python

12- vue django restful framework 打造生鲜超市 -商品详情页,商品收藏

只需要在继承的里面添加这个mixins.RetrieveModelMixin就可以了。

1834
来自专栏智能大石头

NewLife.Net——构建可靠的网络服务

老规矩,先上源码:https://github.com/nnhy/NewLife.Net.Tests

1150
来自专栏java达人

Kafka漫游记

我是一条消息,从我被生产者发布到topic的时候,我就清楚自己的使命:被消费者获取消费。但我一直很纳闷,把我直接推送给消费者不就行了,为什么一定要先推送到类似队...

2537
来自专栏前端开发

小程序的全栈开发新时代

小程序·云开发是微信团队和腾讯云团队共同研发的一套小程序基础能力,简言之就是:云能力将会成为小程序的基础能力。整套功能是基于腾讯云全新推出的云开发(Tencen...

1774
来自专栏大数据文摘

手把手 | 20行Python代码教你批量将PDF转为Word

2975
来自专栏NetCore

不错的node.js入门

关于 本书致力于教会你如何用Node.js来开发应用,过程中会传授你所有所需的“高级”JavaScript知识。本书绝不是一本“Hello World”的教程。...

3747
来自专栏java达人

Kafka漫游记

我是一条消息,从我被生产者发布到topic的时候,我就清楚自己的使命:被消费者获取消费。但我一直很纳闷,把我直接推送给消费者不就行了,为什么一定要先推送到类似队...

4095
来自专栏蓝天

三种web性能压力测试工具http_load webbench ab小结

题记:压力和性能测试工具很多,下文讨论的是我觉得比较容易上手,用的比较多的三种 http_load 下载地址:http://www.acme.com/sof...

1501

扫码关注云+社区

领取腾讯云代金券