【问题标题】:Handle connection losses: reperform request or resend response处理连接丢失:重新执行请求或重新发送响应
【发布时间】:2017-04-04 11:27:27
【问题描述】:

使用 angular-sails,sailsjs 后端通常这样调用:

this.doSomethingWithItem = function(itemID, callback){
        $sails.put('/item/doSomething', {itemID:itemID}).
        success(function (data, status, headers, config) {
            callback(data);
        }).
        error(function (data, status, headers, config){
            alert('Error!');
        });
    };

在后端,大部分 Sails (v0.11.0) 控制器功能都相当简单。一个示例可能如下所示:

  doSomething: function(req, res) {
    var p = req.params.all();
    postgresClientPool.connect(function(err, client, done) {
      client.query("SELECT item_do_something_in_this_awesome_function($1) AS dbreturn", [p.itemID], function(err, result) {
      done();
      if(err) {
          res.status(500).json({success: false});
        }
      else {
          res.json(result.rows[0].dbreturn[0]);
       }
    });
  });
 }

现在由于我们无法影响的原因,我们正在经历相当频繁但相当短的连接丢失(在客户端/浏览器和 nodeJS/sails-Server 之间)。现在的任务是尽可能顺利地为用户处理它们,并避免任何进一步的不便。

因此,如果在正在进行的请求期间连接被中断,则逻辑必须类似于:

  • 检查连接中断是在请求到达服务器之前还是之后发生的。
  • 如果之前发生过:重新执行请求。
  • 如果之后发生:告诉后端重新发送请求的结果。

现在,如何实现?

我不知道在每个服务功能中注册$sails.on('disconnect'... 是否是最好的主意。无论如何,我还没有弄清楚函数执行完成后如何取消注册。

【问题讨论】:

  • 您使用的是标准 HTTP,因此后端自动重新发送响应的选项是不可能的。我建议在 Angular 应用程序中使用一些拦截器,如果您的请求失去连接,请尝试再次发送。应该不会太复杂。

标签: angularjs sails.js


【解决方案1】:

首先,我建议您将业务逻辑从控制器中分离出来。

您可以查看其他答案:sails.js access controller method from controller method

通过这样做,您实际上可以从控制器再次进行调用,而无需做太多事情。

另外,我们将使用 async 模块中的 async.retry 和 async.apply 函数。

例如,假设您将代码移动到api/services/CustomerService.js 中的服务,例如:

module.exports = {
    get: function (customerId, done) {
        // postgresClientPool should be available in a param or globally?
        // I'd prefer assigning it to the sails object...
        // and use it like sails.postgresClientPool
        postgresClientPool.connect(function (err, client, release) {
          if (err) {
            release();
            done(err);
          }
          client.query("SELECT getCustomer($1) AS dbreturn", [customerId],
            function (err, result) {
              release();
              if (err) {
                done(err);
              } else {
                done(undefined, result.rows[0].dbreturn[0]);
              }
            });
        });
      }
    };

然后,在您的控制器中,例如,api/controllers/Customer.js

get: function (req, res) {
    var p = req.params.all();
    async.retry(3, async.apply(CustomerService.get, p.customerID), function (err, result) {
      if (err) {
        res.status(500).json({
          success: false
        });
      } else {
        res.json(result);
      }
    })
  }

您应该在控制器的顶部要求异步。

【讨论】:

  • 感谢您的提示!但是,我不太确定您的答案是否能解决我的实际问题。如果 res.json 由于连接丢失而无法到达客户端(浏览器) - 异步错误是否会在此处出现并触发重试?我对此表示怀疑。
猜你喜欢
  • 2020-11-09
  • 2021-04-27
  • 2020-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-11
  • 2015-08-31
相关资源
最近更新 更多