本系列的例子主要针对node.js环境,但浏览器端的原理应该也是类似的。

本人也是Javascript新手,把自己这段时间学习积累的要点总结下来,希望可以对同样在学习Javascript/node.js的同学有一些参考价值。尽量用通俗的语言帮助大家理解,如果有描述或理解不准确的地方欢迎大家指正,交流。另外本文假定你已经对javascript的语法和异步有一些基本的概念。
本系列会按一般学习异步编程的顺序,首先介绍一下异步的原理,然后介绍各种异步编程的方法,从回调函数开始,然后慢慢进入Promise和Generator等对异步编程体验进行改进的技术。期间也会大概提一下事件监听方式的异步调用,但是因为太多的事件监听会让程序流程变的不清晰,所以不太推荐(其实事件模式本质上也是回调函数)。Promise和Generator才是到目前为止(ES6),最好的异步编程方式。后面也会分享一下自己所理解的这两种方式的对比(网上也有很多争论)。ES7提出了更好的改进方案,希望很快可以抽出时间研究一下,这是后话:)
好,进入本节的正文。
什么是异步?同步异步与阻塞非阻塞有什么关系?
 
node.js的“一切皆异步”的思想很有创意,目的是可以让开发者轻松编写高性能的web服务端,而不会“不小心”就用同步api阻塞了服务器从而影响性能。其他的语言比如php, python, java等基于同步的语言,虽然也有异步api,但毕竟编程人员的“思想上是同步的”,有时候不可避免的会写出阻塞的代码,node.js的目标是造就“思想上是完全异步”的编程人员和编程语言:)
异步跟同步最大的不同就是异步api或函数被“调用”后不会等它运行结束再执行它后面的代码,而是调用之后直接往下执行,异步函数的“执行”实际上是放在“其他地方”,待“执行”完成后再把结果通过回调函数来进行进一步的使用或处理(所以异步函数书写的时候不要用"return"来返回值哦,必须通过回调函数来返回值)。这里为什么强调“调用”和“执行”两个词呢?就是为了更好的理解异步的过程。
打个比喻,你的领导要做个电子报表,笨领导的做法是,在自己电脑上把该统计的统计了,该算的算了,最后生成一张报表,然后用这个报表做接下去的工作;聪明的领导,会发个邮件给下属,把报表的要求写清楚,下属在自己的电脑上把报表做完后,发个邮件把报表交回给领导。在下属做报表的时候,领导可以在自己电脑上继续做其他事情,比如玩游戏、看视频等等(你懂的)。
在上面这个例子中,领导是编程者(你),领导的电脑是当前线程,下属的电脑是另一个线程(如果有多个下属就相当于有个线程池)。做报表这件工作是个异步函数,发邮件给下属相当于调用这个函数,下属电脑上做报表相当于在另一个线程异步执行这个函数,执行完了发邮件把报表发回给领导相当于调用回调函数,领导就可以使用这个报表接着做下面的工作(相当于回掉函数里面的代码)。下属做报表的时候领导完全不用管而是可以继续干其他事情。
通过这个例子可以清楚的看到,领导只能在他自己的电脑(用户线程)上工作,异步的函数都是在下属的电脑上(异步线程)做的。这一点在很多文章当中并没有讲的很清楚,所以容易造成困扰,因为很多人只是一味的强调javascript是单线程的,但单线程怎么能实现异步呢?就并没有讲清楚。其实所谓的单线程是指用户线程是单线程,而另外还有一个或多个线程处理异步代码的执行。
接下来再说说阻塞的问题。很多文章里面在讲解的时候同步异步阻塞非阻塞混为一团,新手很难理解,最容易产生的误解就是同步=阻塞,异步=非阻塞。其实阻塞非阻塞跟同步异步没有任何关系。简单讲,阻塞就是一个api或者函数运行时间过长,而独占cpu导致其他代码不能运行,那么多长时间算阻塞呢?相信这只是一个相对的概念,只要明显影响到程序的性能和用户体验,就算阻塞吧。那跟同步异步是什么关系呢?阻塞的代码如果同步执行就会阻塞到自己后面代码的运行,所以自然而然的就想到异步来执行阻塞的代码,然而异步真能解决阻塞问题吗?下面继续讲。
node.js里面的异步
大家知道Javascript的基本语法跟其他编程语言大同小异,最大的不同就是把异步摆在首位,特别是node.js更是大部分api都是异步的,小量同步api。这与其他大部分语言刚好相反,也给习惯于同步编程思维的同学造成了很大的困扰,就是常说的转不过弯来,习惯性的认为代码是按顺序一行一行的往下执行。
上面介绍了异步非阻塞的概念,那么具体到node.js是怎么实现的呢?这里又会涉及到I/O的概念,具体不讲I/O的细节(操作系统原理都会讲),关键就一点,I/O操作通常比较耗时但不会独占CPU,典型的I/O比如文件读写,远程数据库读写,网络请求等。 先讲耗时,如果用同步API来进行I/O操作,在返回结果之前就只能等待,所以最好的办法上面已经讲过,就是进行异步操作。接着说一下不会霸占CPU的好处。在node.js进程里面,有一个用户线程(javascript所宣称的单线程)和一个异步线程池(用户无法直接访问), 如果跑在异步线程上的代码是阻塞的,那么这种异步根本就起不到消除阻塞的作用,为什么?原因就是阻塞代码会霸占cpu,导致本进程所有代码都等待不管是哪个线程。但是,,,刚刚讲的node.js里面的I/O API都是不会霸占CPU的,所以是非阻塞的,就不会出现这个问题。这就是node.js的最引以为傲的特性之一:异步非阻塞I/O.
上面只是强调异步非阻塞,那么对于真正的阻塞代码,node.js怎么办呢?不好意思。。。单个node.js进程真无能为力,跟同步编程语言相比没什么优势,只能用传统的方式,多进程,多开几个node.js进程,甚至多开几个服务器。任何语言都有它的强项和弱项,node.js的强项就是它本来的设计初衷:让开发者能够轻松的编写高性能的web服务器(进行的最多的就是网络和数据库的I/O操作),而不是做大量的CPU密集型的运算(不过我赶脚,就算要做很多阻塞操作,用多进程和多服务器又有何不可?node.js对此提供了足够的支持)。这样算是回答了上一小节最后的问题了吧:)
要理解javascript异步编程和其他语言同步编程的区别,可以从一个最简单的例子开始。在同步为主的语言中,如果需要等待10秒钟,通常是类似sleep 10之类的语句,在10秒之内整个进程挂起,也就是阻塞10秒。但javascript不是这样,它是使用setTimeout函数,从字面意思就已经可以看出区别了, 设一个timeout的时间, 在这段时间内cpu可以继续运行其他代码, 等10秒时间到了, 就用回调函数的形式来做应该10秒之后才做的事情。

到此,这一节异步编程的原理大概就概括了一下,在进一步深入学习异步编程之前一定要理解的概念。以上都是自己的理解,错误或不准确的地方还望不吝赐教:)
下一节会介绍最基础的javascript的异步编程方式:回调函数,所有其他方式都是基于它的改进。
附注:也许是我读得书少:) 这么久以来没有发现网上有对异步编程讲解的很透彻的文章,在自己学习过的资料当中,朴灵的《深入浅出node.js》是讲解的最深入透彻的,强烈推荐。
转载请标明出处: http://www.cnblogs.com/chrischjh/p/4648395.html

转载于:https://www.cnblogs.com/chrischjh/p/4648395.html

Javascript异步编程之一异步原理相关推荐

  1. python2异步编程_Python 异步编程入门

    本文是写给 JavaScript 程序员的 Python 教程. Python 的异步编程,其他人可能觉得很难,但是 JavaScript 程序员应该特别容易理解,因为两者的概念和语法类似.JavaS ...

  2. python2异步编程_python异步编程 (转载)

    转自:https://zhuanlan.zhihu.com/p/27258289 本文将会讲述Python 3.5之后出现的async/await的使用方法,以及它们的一些使用目的,如果错误,欢迎指正 ...

  3. python2异步编程_python异步编程入门

    这几天看代码,总是会接触到很多异步编程,之前只想着实现功能,从来没考虑过代码的运行快慢问题,故学习一番. 从0到1,了解python异步编程的演进 1.urllib与requests爬虫 reques ...

  4. java jpa 异步编程_异步处理时的JPA

    java jpa 异步编程 几年前,在Java世界中,几乎显而易见的是,每个"企业"类项目都需要JPA与数据库进行通信. JPA是Joel Spolsky描述的" 泄漏抽 ...

  5. 异步编程之异步编程与多线程编程的联系和区别

    1.异步编程与多线程的区别 共同点:异步和多线程两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性 不同点: (1)线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是 ...

  6. php怎么进行异步编程,php异步编程是怎样的?

    前言 传统的 php-fpm 一个进程执行一个请求,要达到多少并发,就要生成多少个进程.更糟糕的是每次请求都需要重新编译执行,导致并发一直上不来.因此出现了 Swoole 和 WorkerMan 两个 ...

  7. android 异步编程,flutter异步编程-事件循环、Isolate、Stream(流)

    事件循环.Isolate 开始前我们需要明白 Dart 是单线程的并且 Flutter 依赖于 Dart 如果你知道js 中的event loop 将很好理解dart的整个异步过程 先看一段代码 im ...

  8. JavaScript异步编程的原理

    1 想说的话 JavaScript异步编程是前端面试中一个重要内容.为了加深我对此部分内容的印象,故写此博客,主要介绍JS异步编程的运行原理. pre 栈队列 2 正文 本文主要是阐述下面这张图的内容 ...

  9. 现代化程序开发笔记(11)——异步编程杂谈

    本系列文章以我的个人博客的搭建为线索(GitHub 仓库:Evian-Zhang/evian-blog),记录我在现代化程序设计中的一些笔记.在这篇文章中,我将以我的理解从头开始梳理一遍异步编程. 从 ...

最新文章

  1. 基于Mixin Network的PHP比特币开发教程 之一:创建机器人
  2. NodeJs开发微信公众号(一)
  3. Java调用ocx控件以及dll
  4. 神经植入物是如何工作的?
  5. Linux--DHCP
  6. libgdx 学习笔记七 Libgdx模块概述
  7. aud to php,HKD to PHP
  8. [转]G++与GCC的区别
  9. php 类自动执行,php类中的魔术方法及类的自动加载
  10. [UOJ455][UER #8]雪灾与外卖——堆+模拟费用流
  11. 在群晖synoboot.img引导文件中加入网卡驱动_群晖DS1819+使用记录
  12. Tableau安装与破解
  13. TOPSIS优劣解距离法
  14. java实现excel数据比对代码_java上传Excel文件并比对数据
  15. Arcgis中的空间插值
  16. 联发科之殇:破碎高端梦
  17. c语言打气球游戏,打气球程序求修改
  18. 倪文迪陪你学蓝桥杯2021寒假每日一题:1.25日(2019省赛A组第3题)
  19. html网页中如何给文字加入下划线
  20. 程序员最大的悲哀是什么?

热门文章

  1. SQL 2005中pivot and unpivot的用法
  2. mongo数据库 备份 还原
  3. 飞船赛——FOJ 1021
  4. Vue nextTick 机制
  5. CVE-2019-2725复现(从环境搭建到getshell)
  6. CSDN-markdown编辑器(保存自CSDN官方)
  7. 山东大学计算机系统原理,山东大学计算机组成原理三套题汇总
  8. 荆门市掇刀石中学2021高考成绩查询,2021年荆门中考所有高中学校排名 荆门重点高中分数线...
  9. 手机号码 mysql 存储类型_2021-01-06:mysql中,我存十亿个手机号码,考虑存储空间和查询效率,用什么类型的字段去存?...
  10. 禅道开源版用户手册_自动化建模 | H2O开源工具介绍