【问题标题】:How can I properly promisify these two database methods for nodejs?如何正确地为 nodejs 提供这两种数据库方法?
【发布时间】:2015-09-16 04:13:51
【问题描述】:

我有一个处理连接设置和池的数据库模块,以及一个依赖于数据库模块来执行查询的查询模块。我正在调整它们以使用 Promises 进行异步调用。到目前为止,I've adapted the query module - 现在我想转换数据库模块。

问题来了:数据库模块应该可以被查询模块直接和隐式使用(目前依赖于回调)。如何在两个模块的方法中使用 Promise,而不会将其变成曲折的小段落迷宫?

这是我到目前为止所做的:

数据库模块

getConnection: function(callback) { //this should return a promise
    this.pool.getConnection(function(error, connection){
        callback(error, connection);
    });
},

查询模块这应该在getConnection 承诺上then,执行查询,然后为它的调用者拒绝/解决

    request: function(queryRequest) {
        return new Promise(function(resolve, reject){
            Database.getConnection(function(error, connection){
                if(error) {
                    reject({error: error, queryRequest: queryRequest});
                } else {
                    connection.query(queryRequest.sql, queryRequest.values, function(error, rows, fields){
                        if(error) {
                            reject({error: error, queryRequest: queryRequest});
                        } else {
                            resolve({rows: rows, fields: fields, queryRequest: queryRequest});
                        }
                        connection.release()
                    });
                }
            });
        });
    },

【问题讨论】:

  • 我不确定您为什么要求我们以问答形式解决您的特定问题,但我不喜欢这类问题。正如我之前所说,作为一个承诺粉丝和蓝鸟贡献者,我不介意在适当的支持渠道中问你的问题,但这个问题不会教给其他用户任何东西。
  • 如果您在此处给出上一个问题的清晰摘要并突出您实际想要做的事情会更好。
  • 这里的问题在哪里?如果这是一个规范的问题,您可能需要选择一些规范的问题来回答。
  • 请在这个问题中添加一个问题。
  • 我在这里猜测了你的意图;请检查修改。

标签: javascript node.js asynchronous promise


【解决方案1】:

getConnection 应该返回一个承诺 [for the connection]

而不是,它应该使用disposer pattern,并调用connection.release()本身:

function withConnection(callback) {
    var pool = this.pool;
    var conn = new Promise(function(resolve, reject) {
        pool.getConnection(function(error, connection){
            if (error)
                reject(error);
            else
                resolve(connection);
        });
    });
    return conn.then(function(connection) {
        var res = conn.then(callback); // safe call
        return res.then(fin); // `finally` shim
        function fin() {
            connection.release();
            return res;
        }
    });
}

function request(queryRequest) {
    return Database.withConnection(function(connection) {
        return new Promise(function(resolve, reject) {
            connection.query(queryRequest.sql, queryRequest.values, function(error, rows, fields) {
                if (error)
                    reject(error);
                else
                    resolve({rows: rows, fields: fields, queryRequest: queryRequest});
            });
        });
    }).catch(function(error) {
        error.queryRequest = queryRequest;
        throw error;
    });
}

【讨论】:

  • 这会因为第一个链中的上下文(和其他一些东西)而失败,但我也不明白你为什么首先要帮助解决这类问题。
  • 我喜欢getConnection中的处理器模式
  • @user2727195 你在使用库吗?
  • @BenjaminGruenbaum 不使用任何库,仅使用原生 JavaScript 承诺。
  • @Bergi this.pool 在 promise 构造函数执行器回调函数中是什么? (什么是this?)
【解决方案2】:

数据库模块

    getConnection: function() {
        return new Promise(function(resolve, reject) {
            this.pool.getConnection(function(error, connection){
                if(error) {
                    reject(error);
                } else {
                    resolve(connection);
                }
            });
        });
    },

查询模块

    execute: function(queryRequest) {
        var self = this;
        this.queryRequest = queryRequest;

        return new Promise(function(resolve, reject) {
            self.resolve = resolve;
            self.reject = reject;
            var promise = Database.getConnection();
            promise.then(self.result.bind(self), self.fault.bind(self));
        });
    },

    result: function(connection) {
        var self = this;
        connection.query(this.queryRequest.sql, this.queryRequest.values, function(error, rows, fields) {
            if (error) {
                self.reject(error);
            } else {
                self.resolve({rows: rows, fields: fields, queryRequest: self.queryRequest});
            }
            connection.release();
        });
    },

    fault: function(info) {
        self.reject(info);
    }

【讨论】:

  • 这个答案没有对正在改变的内容、方式或原因进行任何解释。
  • this.queryRequest = queryRequest;self.resolve = resolve;self.reject = reject; 似乎是一个非常糟糕的主意,因为它不允许并发请求。此外,您似乎在您的execute 方法中使用了promise construction antipattern(埋在resultfault 中)
  • 处理并发请求,每个请求都实例化了一个新的QueryModule
  • @user2727195:但你为什么要这么做?您应该只公开一个简单的query 函数,而不是QueryModule 类(用户可能会在同一个实例上错误地多次调用.execute)。
猜你喜欢
  • 2014-10-24
  • 2013-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 1970-01-01
相关资源
最近更新 更多