【问题标题】:How to promisify your own javascript api which uses another promisified api with Bluebird?如何promisify 你自己的javascript api,它使用另一个promisified api 和Bluebird?
【发布时间】:2015-04-05 20:05:20
【问题描述】:

我有点挣扎。我想在节点中的数据库驱动程序模块上构建一个抽象层。我已经通过执行以下操作来承诺驱动程序模块:

var sql = Promise.promisifyAll(require('sql-driver'));

然后在我自己的 js 文件中,我想像这样包装查询:

function query(queryString, transaction) {
   sql.connectAsync(config).then(function() {

      var req = new sql.Request(transaction);
      req.queryAsync(queryString).then(function(resultSet)) {
          console.log(resultSet);
      });
   });
}

我怎样才能承诺(使用 bluebird),以便我的查询函数也被承诺并返回承诺或 thenable?

更新:

我希望我的包装方法也被承诺,以便用户可以执行以下操作:

var myDbWrapper = require('my-db-wapper');
function getData() {
    myDbWrapper.startTransaction()
    .then(function(transaction) {
        return myDbWrapper.query('select 1 as number', transaction);
     })
    .then(function(resultSet) {
        console.log(resultSet);
     }).
    .catch(function(e) {
        console.error(e);
    });
}

我确定这不是工作代码,只是试图传达这个想法。另外,这个例子只显示了一个查询,没有显示 commit 方法,它也是包装器的一部分。有人可以给我看一个例子吗?使用承诺来完成一个具有多个查询的整个事务,然后如果没有错误则“提交”?

更新 2:

idbehold 下面的示例不允许我做这种事情,假设我们此时不关心交易,只是一个简单的查询:

myDbWrapper.query(queryString, undefined)
.then(function(recordSet) {
   console.log(recordSet);
})
.catch(function(err) {
   console.error(err);
});

我怎样才能让我的查询方法以这种方式工作?

更新 3:

我找到了答案。见下文。

【问题讨论】:

  • 你不需要“承诺”,你只需要return你已经在使用的承诺。
  • 正如 bergi 所说 - 承诺通过返回值起作用 - 如果你希望你的函数被“承诺”,只需从中返回一个承诺 - 这就是它所需要的。
  • 您的 getData 仍然不是 return 正在执行 myDbWrapper.startTransaction
  • getData 只是一个用于测试的函数。我的示例与 getData 无关。我想知道如何构造包装器调用,例如query、startTransaction 以及在进行基于 promise 的事务时如何使用它们。

标签: javascript promise bluebird


【解决方案1】:

只要返回那个承诺:

function query(queryString, transaction) {
   return sql.connectAsync(config).then(function() {
      var req = new sql.Request(transaction);
      return req.queryAsync(queryString);
   }).then(function(resultSet)) {        // You don't actually
      console.log(resultSet);            // need this this part
      return resultSet;                  // unless you need to log
   });
}

【讨论】:

  • 但我希望我的包装器也能被承诺。这个例子是返回一个字符串给查询的调用者。
  • @u84six 调用此函数将返回一个承诺。
  • 那么你能告诉我如何在我更新的示例中使用查询方法和 startTransaction 方法吗?
  • @u84six 好吧,query 函数只接受一个参数,所以我不确定您为什么在示例代码中将 transaction 传递给它。除此之外,您编写的代码应该可以正常工作。
  • @u84six 那么您的示例代码应该完全按照您的预期工作。我认为您不需要进行任何修改。
【解决方案2】:

好的,我想通了,它就在我面前。这是我对 Promises 缺乏了解。大多数关于返回承诺的回答都是正确的,但我不应该返回我正在使用的承诺,我需要像这样创建一个新的承诺:

function query (queryString, transaction) {
   return new Promise(function(resolve, reject) {
        var req = new sql.Request(transaction);
        req.queryAsync(queryString).then(function(resultSet) {
            resolve(resultSet);
        })
        .catch(function(err) {
            reject(err);
        });
    });
}

编辑,不创建新的承诺:

function query (queryString, transaction) {
  var req = new sql.Request(transaction);
  return req.queryAsync(queryString);
}

【讨论】:

  • 你不需要这样做。将现有的 Promise 包装在另一个 Promise 中只会增加内存使用量和代码行数。
  • 我无法让您的示例正常工作。你能给我一个例子,说明如何在你的例子中使用查询方法吗?
  • 我已经编辑了您的帖子,以向您展示等效功能,而无需创建新的承诺。
猜你喜欢
  • 1970-01-01
  • 2018-12-24
  • 1970-01-01
  • 2023-03-18
  • 2015-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多