• 联系我们
  • 地址:湖北武汉三环科技园
  • 电话:159116031100
  • 传真:027-68834628
  • 邮箱:mmheng@foxmail.com
  • 当前所在位置:首页 - java培训
  • 细说JavaScript异步函数发展历程
  •   摘要:对大部分JavaScript开发者而言,async函数仍是新鲜事物,其发展经历了漫长的旅程。本文将梳理总结JavaScript异步函数的发展历程,并表示未来async函数将成为实现异步的主要方式。

      《The Evolution of Asynchronous JavaScript》外文梳理了JavaScript异步函数的发展历程,首先通过回调函数实现异步,之后又经历了Promise/A+、生成器函数,而未来将是async函数的。感谢景庄对该文章的翻译,内容如下:

      对大部分的JavaScript开发者而言,async函数是个新鲜事物,它的发展经历了一个漫长的旅程。因此本文试图梳理总结JavaScript异步函数的发展历程:在不久之前,我们还只能写回调函数来实现异步,然后Promise/A+标准出来了,这之后又出现了生成器函数,而未来显然是async函数的。

      现在让我们一起来回顾这些年来JavaScript异步函数的发展历程吧。

      正如我们所知道的那样,在JavaScript中,异步编程方式只能通过JavaScript语言中的一等函数才能完成:这种方式意味着我们可以将一个函数作为另一个函数的参数,在这个函数的内部可以调用被传递进来的函数(即回调函数)。这也正是回调函数诞生的原因:如果你将一个函数作为参数传递给另一个函数(此时它被称为高阶函数),那么在函数内部,你可以调用这个函数来完成相应的任务。回调函数没有返回值(不要试图用return),仅仅被用来在函数内部执行某些动作。看一个例子:

      Something.save(function(err) { if (err) { //error handling return; // 没有返回值 } console.log(success);});

      的例子中我们演示了一个错误优先的回调函数(error-firstcallbacks),这也是Node.js本身的特点之一,Node.js中所有的核心模块和NPM仓库中的大部分模块在编写时都会遵循这个特点。

      过度使用回调函数所会遇到的挑战:

      也正是基于这些原因,在JavaScript世界中,一直都在寻找着能够让异步JavaScript开发变得更简单的可行的方案。

      一个可行的解决方案之一是async模块。如果你和回调函数打过很久的交道,你也许会深刻地感受到,在JavaScript中如果想要让某些事并行执行,或是串行执行,甚至是使用异步函数来映射(mapping)数组中的元素使用异步函数有多复杂。所以,感谢CaolanMcMahon写了async模块来解决这些问题。

      使用async模块,你可以轻松地以下面这种方式编写代码:

      async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){ // result will be [1, 4, 9]});

      或者更简单些,你可以从只提供Promise风格的接口开始后,并使用诸如callbackify这样的工具来达到向后兼容的目的。其实Callbackify所做的工作和的代码片段类似,但在实现上使用了一个更通用的方法,我你可以去阅读Callbackify的源代码。

      在ES7(还未正式标准化)中引入了Async函数的概念,目前如果你想要使用的话,只能借助于babel这样的语法转换器将其转为ES5代码。(提醒一点:我们现在讨论的是async关键字,而不是NPM中的async包)。

      简而言之,使用async关键字,你可以轻松地达成之前使用生成器和co函数所做到的工作。当然,除了hack之外。

      也许你会问,是否在ES7中有了async关键字,yield就变得不是那么重要了?

      实际上,使用yield实现异步也不过是一种hack罢了,yield意味着懒次序(lazysequences)和迭代器。而await能够完的分离这两点,首先让yield用于其最初的目的,其次使用await来执行异步操作。

      在这背后,async函数实际使用的是Promise,也就是为什么async函数会返回一个Promise的原因。

      因此,我们使用async函数来完成类似于前面代码所完成的工作,可以使用下面这样的方式来重新编写代码:

      async function save(Something) { try { await Something.save(); //等待await后面的代码执行完,类似于yield } catch (ex) { //error handling } console.log(success);}