热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用Promise,Generators和Coroutines编写现代异步Javascript

byWilliamGottschalk威廉戈特沙克(WilliamGottschalk)使用Promise,Generators和Coroutines编写现代异步Ja

by William Gottschalk

威廉·戈特沙克(William Gottschalk)

使用Promise,Generators和Coroutines编写现代异步Javascript (Write Modern Asynchronous Javascript using Promises, Generators, and Coroutines)

Over the years, “Callback Hell” is often cited as one of the most hated design patterns in Javascript for managing concurrency. Just in case you’ve forgotten what that looks like, here is an example of a varying and processing a transaction in Express:

多年来,“回调地狱”经常被称为Javascript中最令人讨厌的并发管理设计模式之一。 万一您忘记了它的外观,下面是在Express中更改和处理事务的示例:

应许是要拯救我们的…… (Promises were supposed to save us…)

I was told that promises would allow us Javascript developers to write asynchronous code as if it were synchronous by wrapping our async functions in a special object. In order to access the value of the Promise, we call either .then or .catch on the Promise object. But what happens when we try to refactor the above example using Promises?

有人告诉我,通过将我们的异步函数包装在一个特殊的对象中,诺言将使我们的Javascript开发人员能够像异步代码一样编写异步代码。 为了访问的承诺的价值,我们称之为要么。然后.catch无极对象。 但是,当我们尝试使用Promises重构上述示例时,会发生什么?

Since each function inside of the callback is scoped, we cannot access the user object inside of the second .then callback.

由于回调内部的每个函数都具有作用域,因此我们无法在第二个.then回调内部访问用户对象。

So after a little digging, I couldn’t find an elegant solution, but I did find a frustrating one:

因此,经过一番挖掘,我找不到一个优雅的解决方案,但确实找到了一个令人沮丧的解决方案:

Just indent your promises so that they have proper scoping.
只是缩进您的诺言,以便他们有适当的范围。

Indent my promises!? So its back to the Pyramid of Doom now?

兑现我的诺言!? 那么现在回到厄运金字塔了吗?

I would argue that the nested callback version looks cleaner and is easier to reason about than the nested promise version.

我认为嵌套的回调版本看起来比嵌套的Promise版本更干净,并且更易于推理。

异步等待将拯救我们! (Async Await Will Save Us!)

The async and await keywords will allow us to write our Javascript code as though it is synchronous. Here is code written with those keywords coming in ES7:

asyncawait关键字将使我们能够像同步代码一样编写Javascript代码。 这是用ES7中的那些关键字编写的代码:

Unfortunately the majority of ES7 features including async/await have not been natively implemented and therefore, require the use of a transpiler. However, you can write code that looks exactly like the code above using ES6 features that have been implemented in most modern browsers as well as Node version 4+.

不幸的是,大多数ES7功能(包括异步 / 等待)尚未本地实现,因此需要使用编译器。 但是,您可以使用大多数现代浏览器以及Node 4+版本中实现的ES6功能编写与上述代码完全相似的代码。

动态二重奏:生成器和协程 (The Dynamic Duo: Generators and Coroutines)

Generators are a great metaprogramming tool. They can be used for things like lazy evaluation, iterating over memory intensive data sets and on-demand data processing from multiple data sources using a library like RxJs.

生成器是一个很棒的元编程工具。 它们可用于诸如延迟评估,遍历内存密集型数据集以及使用RxJ之类的库从多个数据源进行按需数据处理的事情。

However, we wouldn’t want to use generators alone in production code because they forces us to reason about a process over time. And each time we call next, we jump back to our generator like a GOTO statement.

但是,我们不想在生产代码中单独使用生成器,因为它们会迫使我们随着时间的推移对某个过程进行推理。 每次我们调用下一步时,我们都会像GOTO语句一样跳回到生成器。

Coroutines understand this and remedy this situation by wrapping a generator and abstracting away all of the complexity.

协程了解这一点,并通过包装生成器并抽象化所有复杂性来纠正这种情况。

使用协程的ES6版本 (The ES6 version using Coroutine)

Coroutines allow us to yield our asynchronous functions one line at a time, making our code look synchronous.

协程使我们可以一次产生一行异步函数,使我们的代码看起来是同步的。

It’s important to note that I am using the Co library. Co’s coroutine will execute the generator immediately where as Bluebird’s coroutine will return a function that you must invoke to run the generator.

请务必注意,我正在使用Co库。 Co的协程将立即执行生成器,而Bluebird的协程将返回您必须调用以运行生成器的函数。

Let’s establish some basic rules to using coroutines:

让我们建立一些使用协程的基本规则:

  1. Any function to the right of a yield must return a Promise.

    收益率右边的任何函数都必须返回Promise。

  2. If you want to execute your code now, use co.

    如果要立即执行代码,请使用co

  3. If you want to execute your code later, use co.wrap.

    如果要稍后执行代码,请使用co.wrap

  4. Make sure to chain a .catch at the end of your coroutine to handle errors. Otherwise, you should wrap your code in a try/catch block.

    确保在协程的末尾链接.catch来处理错误。 否则,您应该将代码包装在try / catch块中。

  5. Bluebird’s Promise.coroutine is the equivalent to Co’s co.wrap and not the co function on it’s own.

    蓝鸟的Promise.coroutine等同于Co的co.wrap,而不是其本身的co函数。

如果要同时运行多个进程怎么办? (What if I want to run multiple processes concurrently?)

You can either use objects or arrays with the yield keyword and then destructure the result.

您可以将对象或数组与yield关键字一起使用,然后对结果进行解构。

您今天可以使用的库: (Libraries that you can use today:)

Promise.coroutine | bluebirdBluebird is a fully featured Javascript promises library with unmatched performance.bluebirdjs.comcogenerator async control flow goodnesswww.npmjs.comBabel · The compiler for writing next generation JavascriptThe compiler for writing next generation Javascriptbabeljs.ioasyncawaitasync/await for node.jswww.npmjs.com

Promise。协程| bluebird Bluebird是功能齐全Javascript Promise库,具有无与伦比的性能。 bluebirdjs.com 协同 生成器异步控制流优度 www.npmjs.com Babel· 编写下一代Javascript 的编译器编写 下一代Javascript 的编译器 babeljs.io asyncawait node.js的async / await

翻译自: https://www.freecodecamp.org/news/write-modern-asynchronous-Javascript-using-promises-generators-and-coroutines-5fa9fe62cf74/




推荐阅读
  • 本文提供了关于数据库设计的建议和注意事项,包括字段类型选择、命名规则、日期的加入、索引的使用、主键的选择、NULL处理、网络带宽消耗的减少、事务粒度的控制等方面的建议。同时还介绍了使用Window Functions进行数据处理的方法。通过遵循这些建议,可以提高数据库的性能和可维护性。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
  • node.jsrequire和ES6导入导出的区别原 ... [详细]
  • 本文详细介绍了在Linux虚拟化部署中进行VLAN配置的方法。首先要确认Linux系统内核是否已经支持VLAN功能,然后配置物理网卡、子网卡和虚拟VLAN网卡的关系。接着介绍了在Linux配置VLAN Trunk的步骤,包括将物理网卡添加到VLAN、检查添加的VLAN虚拟网卡信息以及重启网络服务等。最后,通过验证连通性来确认配置是否成功。 ... [详细]
  • 本文详细介绍了MySQL表分区的创建、增加和删除方法,包括查看分区数据量和全库数据量的方法。欢迎大家阅读并给予点评。 ... [详细]
author-avatar
国王的驴耳朵要吐槽
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有