Javascript的地狱回调:

2024-02-29 03:59
文章标签 java script 回调 地狱

本文主要是介绍Javascript的地狱回调:,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

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

 

正文从这开始~

 

1. 讲个笑话

 

JavaScript 是一门编程语言

 

2. 异步编程

 

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

 

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

 

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

 

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

 

3. 异步实现

 

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

 

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

  • 回调

  • promise

  • Generator

  • await/async

 

3.1 回调

 

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

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1

 

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

 

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

 

3.2 Promise

 

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

 

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

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1

 

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

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1

 

也可以把函数抽离出来

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1

 

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

 

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

 

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

 

3.3 Generator

 

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

 

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

 

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

 

先看一段代码:

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1

 

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

 

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

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1

 

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

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1

 

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

 

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

 

3.4 await/async

 

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

 

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

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1

 

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

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1

 

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

 

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

 

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

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1

参考文献

  • 回调地狱 @ 奇舞团博客

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

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

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

 

关于本文

作者:@rccoder

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

转载于:https://my.oschina.net/duozuo/blog/800293

这篇关于Javascript的地狱回调:的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/757521

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2