【问题标题】:What is the promise disposer pattern?什么是 Promise Disposer 模式?
【发布时间】:2015-05-09 01:19:21
【问题描述】:

我已经在几个地方读到了 promise disposer 模式,但我不知道它是什么。有人建议我在如下代码中使用它:

function getDb(){
    return myDbDriver.getConnection();
}

var users = getDb().then(function(conn){
     return conn.query("SELECT name FROM users").finally(function(users){
         conn.release();
     });
});

什么是 Promise Disposer 模式以及它如何应用在这里?


注意 - 在本机承诺中,我将 .finally 填充为“添加返回值但执行操作的拒绝和履行处理程序”。如果重要的话,我在这种情况下使用蓝鸟。

【问题讨论】:

标签: javascript promise dispose bluebird


【解决方案1】:

你的代码有问题

上述方法的问题是,如果您在每次执行getDb 后忘记释放连接,您就会发生资源泄漏,当您泄漏的资源用完时可能最终冻结您的应用程序。

你可以在一个地方做:

var users = getDb().then(function(conn){
     return conn.query("SELECT name FROM users");
});

这会泄漏从未关闭的数据库连接。


处理器模式

disposer 模式是一种将代码范围与拥有资源相结合的方法。通过将资源绑定到一个作用域,我们确保它在我们完成它时总是被释放,并且我们不能轻易忘记释放它。它类似于 C# 中的 using、Python 中的 with 和 Java 中的 try-with-resource 以及 C++ 中的 RAII。

看起来像:

 withResource(function(resource){
     return fnThatDoesWorkWithResource(resource); // returns a promise
 }).then(function(result){
    // resource disposed here
 });

在这里应用

如果我们将代码编写为:

function withDb(work){
    var _db;
    return myDbDriver.getConnection().then(function(db){
        _db = db; // keep reference 
        return work(db); // perform work on db
    }).finally(function(){
        if (_db)
            _db.release();
    });
}

我们可以把上面的代码写成:

 withDb(function(conn){
     return conn.query("SELECT name FROM users");
 }).then(function(users){
     // connection released here
 });

处置器模式的用户示例是sequelizeknex(书架的查询构建器)。也可以将它用于更简单的事情,例如在所有 AJAX 请求完成时隐藏加载器。

【讨论】:

  • 你有Promise.using 用法的例子,与你的处理器模式进行比较?
  • 这不是缺少if (_db)吗?如果getConnection 失败,withDb() 目前将拒绝并出现“无法在未定义时调用释放”错误。
  • @Bergi 如果getConnection 失败,您希望您的应用程序崩溃并烧毁(因为 连接池数据库连接 失败并且不是对数据库的操作),但我同意这应该是明确的 - 随意编辑或建议编辑。
  • 是的,你可能想崩溃,但有一个正确的例外,说明了连接问题:-)
  • 这样安全吗?假设两个withDb() 电话连续快速进行。这两个连接会完全独立吗?如果没有,那么您可能需要一种机制,仅当两个请求都得到满足时才释放其中一个连接。
猜你喜欢
  • 1970-01-01
  • 2018-12-22
  • 2012-06-15
  • 2014-08-30
  • 2020-02-02
  • 2018-01-24
  • 2011-08-26
相关资源
最近更新 更多