zoukankan      html  css  js  c++  java
  • 原生的 promise 的局限性

    本文来自:https://ekyu.moe/article/limits-of-native-promise-and-async-await/

    众所周知,Nodejs 已原生支持 Promise 和 async/await 关键字,异步控制已经变得更加方便。

    然而,如今仍有很多人选择使用第三方的 Promise 库(如 bluebird)和类似 async/await 的实现(如 co)。这并不完全是历史原因使然,而是原生 Promise 和 async/await 仍存在着许多不足之处。本文将简单地提出一些,希望能抛砖引玉。

    原生 Promise 方法匮乏

    尽管原生 Promise 提供了Promise.allPromise.race这类基本的方法,但在日常使用中,我们经常需要像Promise.mapPromise.reducePromise.promisifyPromise.delayPromise#isPendingPromise#cancelPromise#timeout这样的方法。尽管要手动实现这些也不算难(除了Promise#cancel),但一些第三方的 Promise 库已经实现了部分这类 feature,就暂且没有必要重复造轮子了。

    17-05-31 更新
    刚刚发现 Nodejs 发布了 8.0.0,Changelog 中有一行吸引了我的注意。

    The new util.promisify() API has been added [99da8e8e02#12442.

    我查了一下文档,确实加了这个方法!好兴奋!!

    原生 Promise 有性能缺陷

    之前看到这个问题有提到原生 Promise 的效率问题,blubird 的作者 Petka Antonov 给出了回答,这里提一下回答中的要点。

    1. V8 的 Promise 是用 JavaScript 而不是 C 实现的。即便使用 C 语言实现 Promise 也不能提高多少性能,因为实际上它所做的提挈都是在与 JavaScript 对象交互。
    2. V8 的 Promise 实现没有像 bluebird 一样的优化,比如它会为 Promise 的 handlers 创建数组,当每个Promise都必须要创建一对数组的时候会消耗大量的内存,而实际上在 99.99% 的情况下都不会将一个 Promise 分支多次,因而对这类情况进行优化能减小内存的使用。
    3. 即便 V8 的 Promise 像 bluebird 一样地被优化,它仍然会受到规范的牵制。这个 benchmark 用了 new Promise(在 bluebird 中这被视为一种 anti-pattern),因为在 ES6 中并没有别的办法来生成一个根 Promise。用new Promise来创建一个 Promise 是极慢的。首先父函数会申请一个闭包,然后传入两个独立的闭包作为参数。算起来每生成一个 Promise 总共要申请三个闭包,然而相对于一个被优化的 Promise 而言,一个闭包都已经是个更昂贵的对象了。

    兼容性

    并不是所有的环境都能随随便便地升级到能支持 Promise 和 async/await 的 node 版本,尤其是 async/await 需要 Nodejs 7.6.0 以上,在我写这篇 blog 的时候 Nodejs 的 LTS 版本还是 6.10.3。而相比之下,很多第三方库都做了这个 polyfill。

    async function 返回的是原生 Promise

    目前没有办法向 async function 的调用返回值注入别的类型的 Promise,它返回的只能是原生的。而上文提到了原生 Promise 目前存在的很多不足,在不得不使用第三方 Promise 库的情况下,也不得不在很多地方放弃 async function。尽管,将一个原生的 Promise 转为 bluebird 的 Promise 倒也不是不可能,例如:

    const Bluebird = require('bluebird');
    
    const someTask = (async () => {})();
    const bluebirdSomeTask = Bluebird.resolve(someTask);
    
    console.log(someTask instanceof Promise);  //=> true
    console.log(bluebirdSomeTask instanceof Bluebird);  //=> true
    

    然而用 Bluebird.resolve 这种方法来进行转换看上去就非常 anti-pattern,也徒增了代码的复杂度。

    知识共享许可协议
    本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。
    本文链接:https://ekyu.moe/article/limits-of-native-promise-and-async-await/

  • 相关阅读:
    C语言strcasecmp()函数:判断字符串是否相等(忽略大小写)
    C语言之strrchr函数
    【Android】adb connect 手机的两种方式
    python web框架介绍对比
    sublime text 3 + python配置,完整搭建及常用插件安装
    Sublime text 3 快捷键:
    sublime text3 插件CTags
    sublime text 3 并列显示
    python 保存csv文件
    pandas 读取文件
  • 原文地址:https://www.cnblogs.com/Kellana/p/7602210.html
Copyright © 2011-2022 走看看