Javascript代码同步化

我最近一直在写js。在这期间,我在群里提的最多的问题就是

函数a在函数b执行之前就执行了,我应该怎么办?

我有一个用python写的网易云音乐的下载器,我最近在试图把它用nodejs重写一遍。
它的逻辑非常简单。但是我写了一半就写不下去了,因为一层一层的回调嵌套,代码已经成了 >形。

js一个重大的特点就是异步非阻塞,但是在一些情况下,下一步的操作需要依赖上一步的执行结果。这样就会有回调中再回调的情况出现。 当业务逻辑一复杂,回调的嵌套越来越多,可读性就会变差,维护起来也会很困难,这就是回调地狱。
node有很多第三方的模块用来将异步调用同步化,来解决这个问题。

回调函数

回调函数简单、容易理解,但是一层层嵌套下来,就形成了回调地狱,不利于代码的阅读。各个部分之间高度耦合,很难维护。

Promise

用resolve和reject抛出返回值,将回调链式化。一方面使代码更优雅,另一方面也使回调更可控。

async/await

async/await本质上是基于generator和promise的语法糖。
async表示这个函数当中存在阻塞的操作, await则表示这个函数会阻塞后面的代码。 await函数返回的结果是一个promise对象,由于 await函数的结果有可能是 reject,因此建议用try…catch包裹 await的函数。

使用上述模块,一方面为了消除回调地狱,另一方面用于真正需要同步的操作。但是不要滥用这些同步化模块。JS作为异步的语言,回调是很自然的模式。尽快转变思维,避免习惯性地用同步的思维去思考js。不然就会像用面向过程的思想来写c++一样。

很多时候,如果仅仅为了避免回调地狱,其实不需要async,generator或promise,只要对代码进行简单的封装即可。就能管理好相当多的回调场景。
不好的写法:

好的写法:

使用babel支持es7

如果想使用es7的新特性(比如async),但是当前环境还不支持。
可以使用bable将较新标准的代码转换为当前环境可以执行的代码

安装babel

配置babel

package.json添加下述依赖,并安装

创建 .babelrc,添加下述内容

转码并运行

向js代码中添加下述内容

运行

其中 origin.js为转码前的es7的代码, dest.js为转码后的可以在当前环境下运行的代码。

参考资料

https://cnodejs.org/topic/5640b80d3a6aa72c5e0030b6
http://aisk.me/using-async-await-to-avoid-callback-hell/
http://stackoverflow.com/questions/10669561/handling-node-js-async-returns-with-require-node-orm
http://masnun.com/2015/11/11/using-es7-asyncawait-today-with-babel.html

Leave a Reply

电子邮件地址不会被公开。 必填项已用*标注

Are you human? Click the Apple...