关于JS单线程、EventLoop、异步I/O的底层特性,我们之前做过详细的拆解,不再赘述。探索完底层机制之后,我们还需要了解代码的组织结构,这是最接近我们日常开发的部分。异步代码的组织方式直接决定了开发和维护的效率,其重要性怎么强调都不为过。低估。虽然底层机制没有改变,但是随着ES标准的发展,异步代码的组织方式一步步发生了巨大的变化。那我们就来一探究竟吧!在回调函数时代,相信很多nodejs初学者都或多或少踩过这样的坑。node中的很多原生API是这样的:fs.readFile('xxx',(err,data)=>{});一个典型的高阶函数,回调函数作为函数参数传递给readFile。但是久而久之,你会发现这种传入回调的方式也有很大的坑,比如下面这样:fs.readFile('1.json',(err,data)=>{fs.readFile('2.json',(err,data)=>{fs.readFile('3.json',(err,data)=>{fs.readFile('4.json',(err,data)=>{});});});});回调中的嵌套回调,也称为回调地狱。这段代码的可读性和可维护性都很差,因为嵌套的层次太多了。而且还有一个比较严重的问题,就是每个任务都可能失败,每个任务失败都需要在回调中处理,增加了代码的混乱度。Promise时代ES6中新增的Promise很好的解决了回调地狱的问题,同时结合了错误处理。写的代码类似下面这样:readFilePromise('1.json').then(data=>{returnreadFilePromise('2.json')}).then(data=>{returnreadFilePromise('3.json')}).then(data=>{returnreadFilePromise('4.json')});链式调用的方式避免了很多嵌套,也符合人们的线性思维模式,极大的方便了异步编程。co+Generator方式使用协程完成Generator功能,使用co库顺序执行代码,用同步的方式写,让异步操作可以顺序执行。co(函数*(){constr1=yieldreadFilePromise('1.json');constr2=yieldreadFilePromise('2.json');constr3=yieldreadFilePromise('3.json');constr4=yieldreadFilePromise('4.json');})async+await方法是ES7中的新关键字。任何添加了async的函数都会默认返回一个Promise对象,更重要的是,async+await还可以让异步代码以同步的方式编写。没有第三方库的支持。constreadFileAsync=asyncfunction(){constf1=awaitreadFilePromise('1.json')constf2=awaitreadFilePromise('2.json')constf3=awaitreadFilePromise('3.json')constf4=awaitreadFilePromise('4.json')}这四种类型简单回顾一下经典的异步编程方法。既然是鸟瞰全局,我觉得知道什么比知道细节更重要,所以就不展开了。不过没关系。下面我们就针对这些具体的解决方案,一步步深入异步编程,了解本质。
