gpt4 book ai didi

javascript - 既然我们有 ES6 promise ,还有理由使用 Q 或 BlueBird 之类的 promise 库吗?

转载 作者:行者123 更新时间:2023-12-01 17:54:04 26 4
gpt4 key购买 nike

关闭。这个问题是opinion-based .它目前不接受答案。












想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题.

5年前关闭。



Improve this question




在 Node.js 添加对 promise 的原生支持后,还有理由使用 Q 或 BlueBird 之类的库吗?

例如,如果您正在启动一个新项目,并且假设在该项目中您没有任何使用这些库的依赖项,我们是否可以说真的没有更多理由使用这些库?

最佳答案

古老的格言说,您应该为工作选择合适的工具。 ES6 promise 提供了基础。如果您想要或需要的只是基础知识,那么这应该/可以为您工作。但是,工具箱中的工具不仅仅是基础工具,而且在某些情况下,这些附加工具非常有用。而且,我认为 ES6 的 promises 甚至缺少一些基本的东西,比如在几乎每个 node.js 项目中都有用的 promisification。

我最熟悉的是Bluebird promise library所以我将主要根据我在那个图书馆的经验来发言。

所以,这里是我使用功能更强大的 Promise 库的 6 大理由

  • 非 promise 异步接口(interface) - .promisify().promisifyAll()对于处理所有那些仍然需要普通回调并且尚未返回 promise 的异步接口(interface)非常有用 - 一行代码创建了整个接口(interface)的 promise 版本。
  • 更快 - Bluebird 是 significantly faster在大多数环境中比原生 promise 。
  • 异步数组迭代的排序 - Promise.mapSeries()Promise.reduce()允许您遍历数组,对每个元素调用异步操作,但对异步操作进行排序,以便它们一个接一个地发生,而不是同时发生。您可以这样做,因为目标服务器需要它,或者因为您需要将一个结果传递给下一个。
  • Polyfill - 如果您想在旧版本的浏览器客户端中使用 Promise,无论如何您都需要一个 polyfill。也可以得到一个有能力的 polyfill。由于 node.js 具有 ES6 promise ,因此您不需要在 node.js 中使用 polyfill,但您可以在浏览器中使用。如果您同时编写 node.js 服务器和客户端,那么在两者中使用相同的 Promise 库和功能可能非常有用(更容易共享代码、环境之间的上下文切换、对异步代码使用通用编码技术等。 .)
  • 其他有用的功能 - Bluebird 有 Promise.map() , Promise.some() , Promise.any() , Promise.filter() , Promise.each()Promise.props()所有这些都是偶尔得心应手的。虽然这些操作可以使用 ES6 promise 和附加代码执行,但 Bluebird 附带这些操作已经预先构建和预先测试,因此使用它们更简单,代码更少。
  • 内置警告和完整堆栈跟踪 - Bluebird 具有许多内置警告,可提醒您注意可能是错误代码或错误的问题。例如,如果你调用一个函数在 .then() 中创建一个新的 promise 。处理程序而不返回该 promise (将其链接到当前的 promise 链中),那么在大多数情况下,这是一个意外错误,Bluebird 会就此向您发出警告。其他内置的 Bluebird 警告是 described here .

  • 以下是有关这些不同主题的更多详细信息:

    PromisifyAll

    在任何 node.js 项目中,我都会立即在任何地方使用 Bluebird,因为我使用了 .promisifyAll()很多标准的 node.js 模块,比如 fs模块。

    Node.js 本身并不像 fs 那样为执行异步 IO 的内置模块提供 promise 接口(interface)。模块。因此,如果您想在这些接口(interface)中使用 Promise,您要么为您使用的每个模块函数手动编写一个 Promise 包装器,要么获取一个可以为您执行此操作的库,或者不使用 Promise。

    Bluebird Promise.promisify()Promise.promisifyAll()提供 node.js 调用约定异步 API 的自动包装以返回 promise 。这是非常有用和节省时间的。我一直在使用它。

    这是一个如何工作的例子:
    const Promise = require('bluebird');
    const fs = Promise.promisifyAll(require('fs'));

    fs.readFileAsync('somefile.text').then(function(data) {
    // do something with data here
    });

    另一种方法是为每个 fs 手动创建自己的 promise 包装器。您想使用的 API:
    const fs = require('fs');

    function readFileAsync(file, options) {
    return new Promise(function(resolve, reject) {
    fs.readFile(file, options, function(err, data) {
    if (err) {
    reject(err);
    } else {
    resolve(data);
    }
    });
    });
    }

    readFileAsync('somefile.text').then(function(data) {
    // do something with data here
    });

    而且,您必须为要使用的每个 API 函数手动执行此操作。这显然没有意义。这是样板代码。您不妨得到一个实用程序来为您完成这项工作。 Bluebird Promise.promisify()Promise.promisifyAll()是这样的实用程序。

    其他有用的功能

    以下是我特别觉得有用的一些 Bluebird 功能(下面有几个代码示例,介绍了这些功能如何节省代码或加快开发速度):
    Promise.promisify()
    Promise.promisifyAll()
    Promise.map()
    Promise.reduce()
    Promise.mapSeries()
    Promise.delay()

    除了有用的功能, Promise.map()还支持并发选项,可让您指定应允许同时运行多少个操作,这在您有很多事情要做但不能压倒某些外部资源时特别有用。

    其中一些既可以称为独立的,也可以用于 promise 本身,该 promise 本身解析为可迭代的,可以节省大量代码。

    Polyfill

    在浏览器项目中,由于您通常希望仍然支持一些没有 Promise 支持的浏览器,因此无论如何您最终都需要一个 polyfill。如果你也在使用 jQuery,你有时可以只使用 jQuery 内置的 promise 支持(尽管它在某些方面非常不标准,可能在 jQuery 3.0 中修复了),但是如果项目涉及任何重要的异步事件,我发现Bluebird 中的扩展功能非常有用。

    更快

    同样值得注意的是,Bluebird 的 promise 似乎比 V8 中内置的 promise 快得多。见 this post有关该主题的更多讨论。

    Node.js 丢失了一件大事

    让我考虑在 node.js 开发中少使用 Bluebird 的原因是,如果 node.js 内置了一个 promisify 函数,那么你可以做这样的事情:
    const fs = requirep('fs');

    fs.readFileAsync('somefile.text').then(function(data) {
    // do something with data here
    });

    或者只是提供已经 promise 的方法作为内置模块的一部分。

    在此之前,我使用 Bluebird 执行此操作:
    const Promise = require('bluebird');
    const fs = Promise.promisifyAll(require('fs'));

    fs.readFileAsync('somefile.text').then(function(data) {
    // do something with data here
    });

    在 node.js 中内置 ES6 promise 支持并且没有任何内置模块返回 promise 似乎有点奇怪。这需要在 node.js 中解决。在那之前,我使用 Bluebird 来保证整个库。因此,感觉现在在 node.js 中实现了大约 20% 的 promise,因为没有一个内置模块允许您在不先手动包装它们的情况下使用它们。

    例子

    这是一个简单的 Promises 与 Bluebird 的 promisify 和 Promise.map() 的例子。用于并行读取一组文件并在完成所有数据后通知:

    简单的 promise
    const files = ["file1.txt", "fileA.txt", "fileB.txt"];
    const fs = require('fs');

    // make promise version of fs.readFile()
    function fsReadFileP(file, options) {
    return new Promise(function(resolve, reject) {
    fs.readFile(file, options, function(err, data) {
    if (err) return reject(err);
    resolve(data);
    });
    });
    }


    Promise.all(files.map(fsReadFileP)).then(function(results) {
    // files data in results Array
    }, function(err) {
    // error here
    });

    Bluebird Promise.map()Promise.promisifyAll()
    const Promise = require('bluebird');
    const fs = Promise.promisifyAll(require('fs'));
    const files = ["file1.txt", "fileA.txt", "fileB.txt"];

    Promise.map(files, fs.readFileAsync).then(function(results) {
    // files data in results Array
    }, function(err) {
    // error here
    });

    这是一个简单的 Promises 与 Bluebird 的 promisify 和 Promise.map() 的例子。从远程主机读取一堆 URL 时,您一次最多可以读取 4 个,但希望在允许的情况下保持尽可能多的并行请求:

    简单的 JS promise
    const request = require('request');
    const urls = [url1, url2, url3, url4, url5, ....];

    // make promisified version of request.get()
    function requestGetP(url) {
    return new Promise(function(resolve, reject) {
    request.get(url, function(err, data) {
    if (err) return reject(err);
    resolve(data);
    });
    });
    }

    function getURLs(urlArray, concurrentLimit) {
    var numInFlight = 0;
    var index = 0;
    var results = new Array(urlArray.length);
    return new Promise(function(resolve, reject) {
    function next() {
    // load more until concurrentLimit is reached or until we got to the last one
    while (numInFlight < concurrentLimit && index < urlArray.length) {
    (function(i) {
    requestGetP(urlArray[index++]).then(function(data) {
    --numInFlight;
    results[i] = data;
    next();
    }, function(err) {
    reject(err);
    });
    ++numInFlight;
    })(index);
    }
    // since we always call next() upon completion of a request, we can test here
    // to see if there was nothing left to do or finish
    if (numInFlight === 0 && index === urlArray.length) {
    resolve(results);
    }
    }
    next();
    });
    }

    Bluebird promise
    const Promise = require('bluebird');
    const request = Promise.promisifyAll(require('request'));
    const urls = [url1, url2, url3, url4, url5, ....];

    Promise.map(urls, request.getAsync, {concurrency: 4}).then(function(results) {
    // urls fetched in order in results Array
    }, function(err) {
    // error here
    });

    关于javascript - 既然我们有 ES6 promise ,还有理由使用 Q 或 BlueBird 之类的 promise 库吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34960886/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com