资讯专栏INFORMATION COLUMN

Promise & Generator——幸福地用同步方法写异步JavaScript

Harpsichord1207 / 1410人阅读

摘要:在这里看尤雨溪大神的这篇小短文,非常精简扼要地介绍了当前常用的。根据尤雨溪大神的说法,的也只是的语法糖而已。对象有三种状态,,。对象通过和方法来规定异步结束之后的操作正确处理函数错误处理函数。方便进行后续的成功处理或者错误处理。

最近在写一个自己的网站的时候(可以观摩一下~Colors),在无意识中用callback写了一段嵌套了5重回调函数的可怕的代码。回过神来的时候被自己吓了一跳,这可不行啊,丑得没法看啊!于是打算尝试一下一些流行的异步的解决方案。经过一番折腾之后...我终于找到了一个令自己满意的方案了(爱不释手)。不过在正式介绍它之前先扯一些其他的相关知识先吧!

1. JavaScript异步解决方案有哪一些

其实异步JavaScript已经不是什么高级的东西了,Nodejs的出现,特别是callback hell令人恐惧的写法已经成功倒逼出了很多很棒的解决方案。在这里看尤雨溪大神的这篇小短文,非常精简扼要地介绍了当前常用的async.js, Promise, co, async/await。个人建议有机会可以都试一下看看。而从个人的角度,我可能会以以下的标准来选择(个人喜好):

需要写爬虫之类控制并发数的我会用async.js;它的有一些API还是很方便的。

写前端的代码的时候可能会比较倾向于考虑Promise,因为一般来说前端的异步场景除了ajax之外貌似也不是很多了。而且之前使用过isomorphic-fetch,感觉很棒。可以看我之前的文章~

后端代码nodejs,那就非co莫属了。根据尤雨溪大神的说法,es7async/await也只是Promise & Generator的语法糖而已。而co,就是结合了PromiseGenerator的神一般的库。而本篇文章主要就是讲co结合PromiseGenerator的异步解决方法。

2. Promise & Generator简单入门

ES6是个好东西,其中的PromiseGenerator可以说是精华的部分之一了。下面简单介绍入门一下Promise以及Generator。这一小节的介绍会很简单,而且也只是这两个新特性的一部分,但是提到的点都是本篇文章所需要的。当然,从学习的角度,应该找书去完全了解一下这两个特性,起码有个印象吧~个人感觉ES6的学习可以去读NCZ的Understanding ECMAScript6或者阮一峰大神的ES6标准入门,都有电子书,很棒!前者语言比较浅显易懂,生动有趣,后者会更加详细,有条理一些。如果您已经对这些特性了如指掌的话,那就不用看这一小节了~

2.1 Promise

Promise有很多版本,也有很多实现的库,但是这里主要是介绍ES6标准的内容。如果阅读以下几条特性觉得不懂的话建议先看看上面两本书相应的章节。

关于promise,首先要意识到它是一种对象。这种对象可以用Promise构造函数来创建,也可以通过Nodejs本身一些默认的返回来获取这种对象。

promise对象有三种状态:PendingFulfilledRejected。分别对应着未开始的状态,成功的状态,以及失败的状态。

这种对象常常封装着异步的方法。在异步方法里面,通过resolvereject来划定什么时候算是成功,什么时候算是错误,同时传参数给这两个函数。这些参数就是异步得到的结果或者错误。

异步有成功的时候,也有错误的时候。对象通过thencatch方法来规定异步结束之后的操作(正确处理函数/错误处理函数)。而thencatchPromise.prototype上的函数,因此“实例化”之后(其实并非真正的实例)可以直接使用。

这个promise对象还有一个神奇的地方,就是可以级联。每一个then里面返回一个promise对象,就又像上面所提的那样,有异步就等待异步,然后选择出规定好的正确处理函数还是错误处理函数。

2.2 Generator

Generator函数是一个带星星函数,而且是一个可以暂停的函数。

函数的内部通过yield来推进函数。通过定义yield后面的值来决定返回的value

函数返回一个遍历器,这个遍历器有一个next方法,可以获取一个对象,这个对象就包含了yield定义好的参数。

关于ES6的知识的其它特性就不谈了,对写同(yi)步代码的话掌握以上这些已经足够了。

3. Co

噔噔噔噔!神奇的Co登场了!这是一个tj大神写的库。使用方法很简单,在Github上的README也讲得很清楚了。主要就是两点:

Co函数里面包裹一个generator函数,在generator函数里面可以yield promise对象,从而达到异步的目的。在Co的内部实现里面是通过递归调用next函数,把每一个promise的值返回出来,从而实现异步转“同步”的写法。

Co函数返回一个promise对象,可以调用thencatch方法来对Generator函数返回的结果进行传递。方便进行后续的成功处理或者错误处理。

4. 如何用同步的写法写异步的代码

下面展示一段异步处理的代码,可以看到,同步的写法写异步真的很爽...

function *foo(res, name, newPassword, oldPassword) {
  try {
    // yield一个promise对象,如果有错误就会被后面的catch捕捉到,成功就会返回user。
    const user = yield new Promise(function(resolve, reject) {
      // 常见的数据库读取星系
      User.get(name, function(err, user) {
        if(err) reject(err)
        resolve(user)
      })
    })

    if(user.password != oldPassword) {
      return res.send({errorMsg:"密码输入错误!"})
    }

    // 看到这一个异步函数和上一个的异步在写法上是基本上“同步”的,没有了相互嵌套,很优雅~也更加方便了debug~
    yield new Promise(function(resolve, reject) {
      User.update(name, newPassword, function(err) {
        if(err) reject(err)
        res.send({msg: "你成功更换密码了!"})
        resolve()
      })
    })

  } catch(e) {
    console.log("Error:", e)
    return res.send({errorMsg:"Setting Fail!"})
  }
}

// 使用的话就直接调用co包含对应的Generator函数即可。
co(foo(res, name, newPassword, oldPassword))
5. 总结

适合使用场景的方法才是最好的方法。但是当你在写Node的时候开始受到回掉地狱的困扰的时候,不妨尝试一下Co?用同步写法写异步的感觉真的很不赖啊!

如果文中有某些地方有错误或者不妥当的地方,欢迎指出来,感激不尽!互相学习才能进步嘛~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/91069.html

相关文章

  • ES6&ES7中的异步Generator函数与异步编程

    摘要:传统的异步方法回调函数事件监听发布订阅之前写过一篇关于的文章,里边写过关于异步的一些概念。内部函数就是的回调函数,函数首先把函数的指针指向函数的下一步方法,如果没有,就把函数传给函数属性,否则直接退出。 Generator函数与异步编程 因为js是单线程语言,所以需要异步编程的存在,要不效率太低会卡死。 传统的异步方法 回调函数 事件监听 发布/订阅 Promise 之前写过一篇关...

    venmos 评论0 收藏0
  • 细说JS异步发展历程

    摘要:换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。参考文章珠峰架构课墙裂推荐细说异步函数发展历程异步编程谢谢各位小伙伴愿意花费宝贵的时间阅读本文,如果本文给了您一点帮助或者是启发,请不要吝啬你的赞和,您的肯定是我前进的最大动力。知其然知其所以然,首先了解三个概念: 1.什么是同步? 所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了...

    Alfred 评论0 收藏0
  • 细说JS异步发展历程

    摘要:参考文章珠峰架构课墙裂推荐细说异步函数发展历程异步编程谢谢各位小伙伴愿意花费宝贵的时间阅读本文,如果本文给了您一点帮助或者是启发,请不要吝啬你的赞和,您的肯定是我前进的最大动力。 知其然知其所以然,首先了解三个概念: 1.什么是同步? 所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由调用者主动等待这个调用的结果。此调...

    RiverLi 评论0 收藏0
  • 简单理解Javascript的各种异步流程控制方法

    摘要:所以仅用于简化理解,快速入门,依然需要阅读有深入研究的文章来加深对各种异步流程控制的方法的掌握。 原文地址:http://zodiacg.net/2015/08/javascript-async-control-flow/ 随着ES6标准逐渐成熟,利用Promise和Generator解决回调地狱问题的话题一直很热门。但是对解决流程控制/回调地狱问题的各种工具认识仍然比较麻烦。最近两天...

    makeFoxPlay 评论0 收藏0
  • 探索Javascript 异步编程

    摘要:因为浏览器环境里是单线程的,所以异步编程在前端领域尤为重要。除此之外,它还有两个特性,使它可以作为异步编程的完整解决方案函数体内外的数据交换和错误处理机制。 showImg(https://segmentfault.com/img/bVz9Cy); 在我们日常编码中,需要异步的场景很多,比如读取文件内容、获取远程数据、发送数据到服务端等。因为浏览器环境里Javascript是单线程的,...

    Salamander 评论0 收藏0

发表评论

0条评论

Harpsichord1207

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<