【问题标题】:Node.js, mongo, promises - passing an argument to the then functionNode.js、mongo、promises - 将参数传递给 then 函数
【发布时间】:2013-12-12 06:36:11
【问题描述】:

使用 node.js,通过 promises 而不是回调,通过指定用户 id 从 mongo 检索用户对象。数据库访问使用require('mongodb').Db

调用从以下代码的底部开始:findByIdPromise(userId)
collection.findOne() 需要 userId 作为参数,但 then() 调用函数时使用 promise 作为单个参数。

为了绕过这个限制,我传递了then() 一个对象finder,它具有预设的userId 属性,以及一个函数findUser,它接受集合承诺,并调用集合的findOne,将预设的userId 传递给它。
这是一个半体面的方法吗?

UserProvider.prototype.getCollectionPromise = function () {
    var deferred = q.defer();
    var resolve = deferred.resolve;

    var collectionCallback = function (error, usersCollection) {
        if (error) {
            throw new Error(error);
        } else {
            resolve(usersCollection);
        }
    };
    this.db.collection(CollectionName, collectionCallback);
    return deferred.promise;
};

UserProvider.prototype.findOnePromise = function () {
    var userId;
    var setUserId = function (id) { this.userId = id; };

    var deferred = q.defer();
    var resolve = deferred.resolve;

    var findUser = function (coll) {
        coll.findOne(
            { _id: id },
            function(error, result) {
                if (error) {
                    throw new Error(error);
                } else {
                    resolve(result);
                }
            }
        );
    };
    return deferred.promise;
};

UserProvider.prototype.findByIdPromise = function(id) {
    var finder = new UserProvider.findOnePromise();
    finder.setUserId(id);

    return this.getCollectionPromise().then(finder.findUser);
};

【问题讨论】:

  • “最佳”是非常主观的,因为我不会尝试在 MongoDB API 上分层承诺 API。
  • 嗨,WiredPrairie,我不能说我认为帖子的那一行会受到批评。我已将“最佳”更改为“半体面”,以免暗示我认为我的解决方案可能具有出色的竞争力。我是 node、mongo 和 promises 的新手,所以摸不着头脑。为什么不对 Mongo 使用 Promise?
  • @10cls 大多数为节点编写的库都使用回调而不是承诺。据我所见,所有标准库都这样做。您最终将包装几乎所有您想使用的库,以便将其转换为 Promise,这是非常不必要的工作。
  • 10cls,代码真的有效吗?我猜这不是出于各种原因,但您的问题被表述为Code Review 而不是“请帮我解决它”。我很困惑。
  • 嗨甜菜根,我还没有运行它。我取消了调用此代码的代码,发现我必须使用相同的(反)模式来传递参数。想我应该问这种情况应该如何处理 - (反)模式有效,但我怀疑它在概念上是方形钉,圆孔,或错误,或非惯用,或笨拙,并且需要修复。希望混乱消除。

标签: node.js mongodb promise


【解决方案1】:

在 Node.js 中执行异步工作的标准方法是通过回调,通常是函数的最后一个参数,它将错误作为其第一个参数,并将任何后续参数作为返回值。这是标准库(即内置包)以及大多数使用这种风格的流行 npm 模块的标准。

当然,如果您愿意,完全欢迎您使用 Promise。但是,我建议不要这样做;您最终将包装几乎所有您使用的库,以便将其从回调转换为承诺,这不是一个特别有趣的练习。

注意:我知道的唯一一个使用 Promise 并且相当流行的例外是 selenium-webdriver。据我所知,它使用 Promise,因此使用它编写的代码看起来与其他 selenium 库尽可能相似,它们都是同步的。

【讨论】:

  • 是的,我同意亚伦的观点。如果您要使用 node,您可能还会使用很多 npm 库,而与约定作斗争只会让您更加头疼(而且我们不需要更多具有异步编程的库;) .建议您查看 caolan 的异步库以处理复杂性:npmjs.org/package/async
  • 使用 q (github.com/kriskowal/q) 你可以同时使用 promise-style + callback-style 而无需额外的努力使用 Q.nodeify。请参阅此答案 stackoverflow.com/a/20153874/12388 或此实际示例 github.com/palmerabollo/rest-confidence-client/blob/master/…
  • Promises 是 ES6 的一部分,也是 Chrome 的一部分,并且很可能会进入 node.js 的核心。它们适用于各种库,并且支持在节点库中继续增长。也正如 Guido 所说,q 允许您轻松包装节点样式函数(错误,数据)回调。
猜你喜欢
  • 2015-12-30
  • 1970-01-01
  • 2014-07-13
  • 1970-01-01
  • 2018-04-06
  • 1970-01-01
  • 2018-02-04
相关资源
最近更新 更多