基本概念

异步

ES6 所谓"异步",简单说就是一个任务不是连续完成的,可以理解成该任务被人为分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段。

比如,有一个任务是读取文件进行处理,任务的第一段是向操作系统发出请求,要求读取文件。然后,程序执行其他任务,等到操作系统返回文件,再接着执行任务的第二段(处理文件)。这种不连续的执行,就叫做异步。

相应地,连续的执行就叫做同步。由于是连续执行,不能插入其他任务,所以操作系统从硬盘读取文件的这段时间,程序只能干等着。

回调函数

JavaScript 语言对异步编程的实现,就是回调函数。所谓回调函数,就是把任务的第二段单独写在一个函数里面,等到重新执行这个任务的时候,就直接调用这个函数。回调函数的英语名字callback,直译过来就是"重新调用"。

读取文件进行处理,是这样写的。

  1. fs.readFile('/etc/passwd', 'utf-8', function (err, data) {
  2. if (err) throw err;
  3. console.log(data);
  4. });

上面代码中,readFile函数的第三个参数,就是回调函数,也就是任务的第二段。等到操作系统返回了/etc/passwd这个文件以后,回调函数才会执行。

一个有趣的问题是,为什么 Node 约定,回调函数的第一个参数,必须是错误对象err(如果没有错误,该参数就是null)?

原因是执行分成两段,第一段执行完以后,任务所在的上下文环境就已经结束了。在这以后抛出的错误,原来的上下文环境已经无法捕捉,只能当作参数,传入第二段。

Promise

回调函数本身并没有问题,它的问题出现在多个回调函数嵌套。假定读取A文件之后,再读取B文件,代码如下。

  1. fs.readFile(fileA, 'utf-8', function (err, data) {
  2. fs.readFile(fileB, 'utf-8', function (err, data) {
  3. // ...
  4. });
  5. });

不难想象,如果依次读取两个以上的文件,就会出现多重嵌套。代码不是纵向发展,而是横向发展,很快就会乱成一团,无法管理。因为多个异步操作形成了强耦合,只要有一个操作需要修改,它的上层回调函数和下层回调函数,可能都要跟着修改。这种情况就称为"回调函数地狱"(callback hell)。

Promise 对象就是为了解决这个问题而提出的。它不是新的语法功能,而是一种新的写法,允许将回调函数的嵌套,改成链式调用。采用 Promise,连续读取多个文件,写法如下。

  1. var readFile = require('fs-readfile-promise');
  2. readFile(fileA)
  3. .then(function (data) {
  4. console.log(data.toString());
  5. })
  6. .then(function () {
  7. return readFile(fileB);
  8. })
  9. .then(function (data) {
  10. console.log(data.toString());
  11. })
  12. .catch(function (err) {
  13. console.log(err);
  14. });

上面代码中,我使用了fs-readfile-promise模块,它的作用就是返回一个 Promise 版本的readFile函数。Promise 提供then方法加载回调函数,catch方法捕捉执行过程中抛出的错误。

可以看到,Promise 的写法只是回调函数的改进,使用then方法以后,异步任务的两段执行看得更清楚了,除此以外,并无新意。

Promise 的最大问题是代码冗余,原来的任务被 Promise 包装了一下,不管什么操作,一眼看去都是一堆then,原来的语义变得很不清楚。

那么,有没有更好的写法呢?

Generator函数的基本概念相关推荐

  1. 【ES6】Generator函数详解

    [ES6]Generator函数详解 一.Generator函数简介 基本概念 函数写法 yield关键字介绍 二.next方法的参数 三.for...of循环 四.关于普通throw()与Gener ...

  2. Generator函数语法

    Generator函数语法 基础概念 *星号的位置 next方法的参数 tips 基础概念 Generator 函数是 ES6 提供的 种异步编程解决方案,语法行为与传统函数完全不同. 执行 Gene ...

  3. Generator函数的语法以及异步的应用

    基本概念 Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同.Generator函数有多种理解角度.语法上,首先可以把它理解成,Generator函数是一个状态机,封 ...

  4. Generator 函数的含义与用法

    异步编程对 JavaScript 语言太重要.JavaScript 只有一根线程,如果没有异步编程,根本没法用,非卡死不可. 以前,异步编程的方法,大概有下面四种. 回调函数 事件监听 发布/订阅 P ...

  5. setwindowshookex回调函数不执行_ECMAScript 6 入门教程—Generator 函数的异步应用

    作者 | 阮一峰异步编程对 JavaScript 语言太重要.JavaScript 语言的执行环境是"单线程"的,如果没有异步编程,根本没法用,非卡死不可.本章主要介绍 Gener ...

  6. Generator 函数的异步应用

    异步编程对 JavaScript 语言太重要.Javascript 语言的执行环境是"单线程"的,如果没有异步编程,根本没法用,非卡死不可.本章主要介绍 Generator 函数如 ...

  7. “睡服”面试官系列第二十篇之generator函数的异步应用(建议收藏学习)

    目录 1. 传统方法 2. 基本概念 2.1异步 2.2回调函数 2.3Promise 3. Generator 函数 3.1协程 3.2协程的 Generator 函数实现 3.3Generator ...

  8. “睡服”面试官系列第十八篇之generator函数的语法(建议收藏学习)

    目录 1简介 1.1基本概念 1.2yield 表达式 1.3与 Iterator 接口的关系 2. next 方法的参数 3. for...of 循环 4. Generator.prototype. ...

  9. go 协程回调函数 传入参数_ECMAScript 6 入门教程—Generator 函数的异步应用

    作者 | 阮一峰异步编程对 JavaScript 语言太重要.JavaScript 语言的执行环境是"单线程"的,如果没有异步编程,根本没法用,非卡死不可.本章主要介绍 Gener ...

最新文章

  1. 23种设计模式及OOP7大原则
  2. linux mint 最新版,Linux Mint安装最新版R
  3. chrome扩展程序_如何创建Chrome扩展程序
  4. day_01 解析简单的程序
  5. 2010上半年网络工程师上午试题分析与解答
  6. 团队项目:过山车游戏的设想
  7. Spring4.x(8)---Spring整合Junit
  8. Python if语句Demo
  9. 机器学习算法总结之聚类:K-means
  10. 规划以及安装Exchange2007
  11. poj 2318 TOYS
  12. 商城app源码_多商户商城源码系统有什么优势呢?
  13. 计算机道德 英语作文,关于道德英语作文
  14. cogs908. 校园网
  15. Android模拟PC键盘输入法,黑科技:用电脑键盘代替手机输入法
  16. python挂机脚本怎么运行,Python实现自动挂机脚本(基础篇)
  17. linux mysql changed limits_ubuntu下mysql提示Changed limits: max_open_files:1024解决办法
  18. 全差分运放阻抗匹配计算(四)
  19. 709元我上了斐讯K2P的车
  20. 省市县数十万数据集PM2.5面板数据(1998-2020年)

热门文章

  1. Week 1:那些值得一阅的好文章
  2. 有符号数与无符号数间的转换
  3. Oracle dataGuard专题:Rman通过duplicate创建standby
  4. 网络(8)-HTTP、Socket、TCP、UDP的区别和联系
  5. SpringBoot2.0.3 + SpringSecurity5.0.6 + vue 前后端分离认证授权
  6. Meerkat倒下想到的:社交巨头的后院不容置喙
  7. Ubuntu下 5步安装nginx记录
  8. 译:重置/还原Windows IIs设置为默认设置
  9. svn 版本控制操作命令
  10. 程序员的奋斗史(二)——今天你跑步了吗