文档章节

Javascript的地狱回调:

duozuo2006
 duozuo2006
发布于 2016/12/05 18:54
字数 1203
阅读 6
收藏 0
点赞 0
评论 0

前言

本文由@rccoder投稿分享。作者总结了四种方式来进行异步操作。

 

正文从这开始~

 

1. 讲个笑话

 

JavaScript 是一门编程语言

 

2. 异步编程

 

JavaScript 由于某种原因是被设计为单线程的,同时由于 JavaScript 在设计之初是用于浏览器的 GUI 编程,这也就需要线程不能进行阻塞。

 

所以在后续的发展过程中基本都采用异步非阻塞的编程模式。

 

简单来说,异步编程就是在执行一个指令之后不是马上得到结果,而是继续执行后面的指令,等到特定的事件触发后,才得到结果。

 

也正是因为这样,我们常常会说: JavaScript 是由事件驱动的。

 

3. 异步实现

 

用 JavaScript 构建一个应用的时候经常会遇到异步编程,不管是 Node 服务端还是 Web 前端。

 

那如何去进行异步编程呢?就目前的标准以及草案来看,主要有下面的几种方式:

  • 回调

  • promise

  • Generator

  • await/async

 

3.1 回调

 

这种异步的方式是最基础的实现,如果你曾经写过一点的 Node, 可能经常会遇到这样的代码:

 

如此,connection.query() 是一个异步的操作,我们在调用他的时候,不会马上得到结果,而是会继续执行后面的代码。这样,如果我们需要在查到结果之后才做某些事情的话,就需要把相关的代码写在回调里面,如果涉及到多个这样的异步操作,就势必会陷入到回调地狱中去。

 

这种回调地狱不仅看起来很不舒服,可读性比较差;除此之外还有比较重要的一点就是对异常的捕获无法支持。

 

3.2 Promise

 

Promise 是 ES 2015 原生支持的,他把原来嵌套的回调改为了级联的方式。

 

一般着,我们对一个 Promise 可以这样写:

 

如果要涉及到多个异步操作的顺序执行问题,我们可以这样写:

 

也可以把函数抽离出来

 

我们只需要 return 一个 Promise 即可实现这种多个异步操作的顺序执行。

 

粗略来看,这是一个比较优雅的异步解决方案了,并且在 Promise 中我们也可以实现分级的 catch。

 

但对于之前接触过其他语言的同学来说还是比较别扭的。那能否用同步的方式来书写异步呢?

 

3.3 Generator

 

在 ES 2015 中,出现了 Generator 的语法,熟悉 Python 的同学肯定对这种语法有点了解。

 

简单来说,Generator 可以理解为一个可以遍历的状态机,调用 next 就可以切换到下一个状态。

 

在 JavaScript 中,Generator 的 function 与 函数名之间有一个 *, 函数内部使用 yield 关键词,定义不同的状态。

 

先看一段代码:

 

上面的这段代码是借助 TJ 的 co 实现的,依照约定,co 中 yield 后面只能跟 Thunk 或者 Promise.

 

co 的实现代码很短,简单来说大体是这样:

 

简单来说就是一直借助 generator 的 next 进行迭代,直到完成这个异步操作才返回。当前人家官方的 co 是 200 行代码,支持异步操作的并行:

 

但如果我们使用 co,强迫症们就会觉得这不是标准的写法,有点 hack 小子的感觉。

 

幸运的是,在 ES 2016 的草案中,终于提出了标准的写法。

 

3.4 await/async

 

这是在 ES 2016 中引入的新关键词,这将在语言层面彻底解决 JavaScript 的异步回调问题,目前可以借助 babel 在生产环境中使用。使用 await/async 可以让异步的操作以同步的方式来写。

 

使用方法和 co 非常类似,同时也支持同步写法的异常捕获。

 

如果上述的代码完全用 Promise 实现,极有可能是下面的代码:

 

相比较来说,await/async 解决了完全使用 Promise 的一个极大痛点——不同Promise之间共享数据问题:

 

Promise 需要设定外层数据开始共享,这样就需要在每个then里面进行赋值,而 await/async 就不存在这样的问题,只需要以同步的方式去写就可以了。

 

await/async 对异常的支持也是特别好的:

参考文献

  • 回调地狱 @ 奇舞团博客

  • ES6 Generator介绍 @ 腾讯全端 AlloyTeam 团队 Blog

  • 使用Generator解决回调地狱 @ 腾讯全端 AlloyTeam 团队 Blog

  • 「大概可能也许是」目前最好的 JavaScript 异步方案 async/await @ LearnClound

 

关于本文

作者:@rccoder

原文:https://github.com/rccoder/blog/issues/17

© 著作权归作者所有

共有 人打赏支持
duozuo2006
粉丝 0
博文 10
码字总数 8728
作品 0
北京
谈谈Javascript异步代码优化

前言 在实际编码中,我们经常会遇到Javascript代码异步执行的场景,比如ajax的调用、定时器的使用等,在这样的场景下也经常会出现这样那样匪夷所思的bug或者糟糕的代码片段,那么处理好你的J...

劳卜 ⋅ 05/11 ⋅ 0

谈谈JavaScript异步代码优化

关于 微信公众号:前端呼啦圈(Love-FED) 我的博客:劳卜的博客 知乎专栏:前端呼啦圈 前言 在实际编码中,我们经常会遇到Javascript代码异步执行的场景,比如ajax的调用、定时器的使用等,...

劳卜 ⋅ 05/11 ⋅ 0

Modern JS中的流控制:CallBacks->Promises->Async/Await

今天来聊一聊JS中的异步发展,还有推荐的异步调用写法. 单线程模式 JS运行在一个单处理线程上运行。当你操作一个标签时,其他的JS代码就会等待该操作执行完毕。浏览器的DOM操作不会发生在并行...

含笑666 ⋅ 06/06 ⋅ 0

JavaScript异步精讲,让你更加明白Js的执行流程!

JavaScript异步精讲,让你更加明白Js的执行流程! 问题点 什么是单线程,和异步有什么关系 什么是 event-loop jQuery的Deferred Promise 的基本使用和原理 async/await(和 Promise的区别、联...

推荐码发放 ⋅ 05/28 ⋅ 0

如何使用koa2+es6/7打造高质量Restful API

前言 如今nodejs变得越来越火热,采用nodejs实现前后端分离架构已被多数大公司所采用。 在过去,使用nodejs大家首先想到的是TJ大神写的express.js,而发展到如今,更轻量,性能更好的koa已然...

Jack088 ⋅ 06/12 ⋅ 0

swt browser控件与java交互

1、java调用browser页面里的js [javascript] view plain copy final Browser browser = new Browser(shell, SWT.FILL_WINDING); browser.evaluate("fun()");//fun是一个定义好的js函数 2、j......

xiaomin0322 ⋅ 06/12 ⋅ 0

从一道执行题,了解浏览器中JS执行机制

执行题 JavaScript本身是一门单线程语言 为什么 是单线程的?作为浏览器脚本语言,JavaScript 的主要用途是与用户互动,以及操作 DOM 。这决定了它只能是单线程,否则会带来很复杂的同步问题...

COC马里奥 ⋅ 05/30 ⋅ 0

php中ajax跨域请求---小记

php中ajax跨域请求---小记 前端时间,遇到的一个问题,情况大约是这样: 原来的写法: 前端js文件中: $.ajax({   type:'get',   url:'http://wan.xxx.com/xxx.js',   success:functio...

thinkyoung ⋅ 2015/08/31 ⋅ 0

android webview获取网页源代码,js执行前后

webview获取网页源代码分两种,一种是js执行前,一种是js执行后 1.js执行前 URL url = new URL(path); // 根据URL // 打开连接,URL.openConnection函数会根据URL的类型,返回不同的URLConn...

tan6458 ⋅ 2017/07/12 ⋅ 0

javaFX实例1-webView实现简单浏览器

webView: 是一个管理webEngine和显示它中间内容的节点。这个对象只能从fx的线程中创建。 webEngine: 是一个管理网页的不可见控件,它可以加载网页,创建文档模型,运行javascript,加载必要...

xiaomin0322 ⋅ 06/13 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Windows下安装运行phpMyAdmin

首先确保安装了phpMyAdmin,其次要求服务器是打开的。 如果是在Windows下,建议下载安装WampServer,这是一个集成软件,集成了Apache+MySQL+PHP的开发环境,而且也自带了phpMyAdmin这个软件。...

临江仙卜算子 ⋅ 9分钟前 ⋅ 0

jdk1.8 安装及环境变量配置

1.根据jdk 的软件安装包,首先安装,jdk,

kuchawyz ⋅ 9分钟前 ⋅ 0

给Java字节码加上”翅膀“的JIT编译器

给Java字节码加上”翅膀“的JIT编译器 上面文章在介绍Java的内存模型的时候,提到过由于编译器的优化会导致重排序的问题,其中一个比较重要的点地方就是关于JIT编译器的功能。JIT的英文单词是...

九劫散仙 ⋅ 10分钟前 ⋅ 0

PCI简介(二)

1.x86处理器系统地址空间简介 1.1 CPU地址空间 CPU地址空间是指CPU所能寻址的空间大小,比如对于32位CPU来说,其所能寻址的空间大小为0~4G。这是由CPU自身的地址总线数目决定的。这段空间也被...

深山野老 ⋅ 11分钟前 ⋅ 0

spring中的InitializingBean接口

好久没更博了,真有点怀念,前段时间刚和上家公司say bye,这次进的是电商公司,今天刚开始看代码,逻辑很复杂。 今天看的注册功能,里面见到一个知识点,现在记录一下,今天看项目时见到里面...

千元机爱好者 ⋅ 13分钟前 ⋅ 0

机器学习:数据预处理之独热编码(One-Hot)

前言 ———————————————————————————————————————— 在机器学习算法中,我们经常会遇到分类特征,例如:人的性别有男女,祖国有中国,美国,法国等。 ...

NateHuang ⋅ 21分钟前 ⋅ 0

MyBatis之输入与输出(resultType、resultMap)映射

在MyBatis中,我们通过parameterType完成输入映射(指将值映射到sql语句的占位符中,值的类型与dao层响应方法的参数类型一致),通过resultType完成输出映射(从数据库中输出,通过dao层的方法查...

瑟青豆 ⋅ 22分钟前 ⋅ 0

屏蔽运营商广告劫持

在今天早上我查找知乎时再次遇到了恶心的运营商广告劫持,右下角硕大的广告直接让知乎挂掉了,我刷了五次知乎才好,之前休息的时候逛知乎也是多次加载错误,估计也是这劫持的锅,相信各位也遇...

gcudwork ⋅ 25分钟前 ⋅ 0

java web 进度条实现原理

资料路径 https://blog.csdn.net/fengsheng5210/article/details/79305026

zaolonglei ⋅ 26分钟前 ⋅ 0

命令行输出java版本与环境变量配置的不一样问题解决

问题:java10刚出来,本着好奇的心,急切的装了体验一下,然后实际项目需求还是java8,所以体验完了就把环境变量改回来了,但是出现了一个问题,命令行输出java版本与环境变量配置的不一样,...

消散了的诗意 ⋅ 28分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部