【问题标题】:How should I handle http requests whose lifetime is longer than their calling scope?我应该如何处理生命周期长于调用范围的 http 请求?
【发布时间】:2016-08-19 15:59:25
【问题描述】:

所以,我的一个 $angular 作用域在用户交互时启动一个 $http 请求。该请求需要很长时间才能运行,并且当它的承诺被解决时,用于启动请求的范围可能已经消失。

现在,很明显,因为 js 是一门很好的语言,所以范围对象仍然存在,因为它已在 promise 处理程序变量范围中被捕获,所以,最坏的情况是,我甚至要更新范围变量尽管范围完全未使用。然而,在这个处理程序中可能发生的事情之一是:

$state.go("^");

现在,如果与此范围关联的 ui-router 状态仍处于活动状态,这将正常工作,但是当用户感到无聊时,他们倾向于单击并返回另一个执行 $state.go( "^") 不是一个好主意。

我可以:

  1. 在 promise 处理程序中,检查 .go("^") 之前的当前状态是否仍然“相同”(我将跳过“相同”的真正含义)
  2. 以某种方式确保 $http 请求处理程序在 $scope 被销毁时被取消。

很明显,1. 是……可怕。 2. 还不够痛:

$scope.running_http_request = $http.get(...).then(function (result) {...});
$scope.$on("destroy", function () {
  $scope.running_http_request.cancel()
});

(是的,$http 请求没有本机取消方法,但添加它并不太可怕,我可以这样做)。

现在,所有这一切都非常痛苦:有没有更好的方法来确保如果我的 $scope 消失了,那么该范围内待处理的内容也会消失?

【问题讨论】:

  • 可以在角度stackoverflow.com/a/17328336/2169630中取消HTTP请求
  • 看看this问题
  • 我会选择第一个,因为它似乎更容易实现。不取消挂起的 http 请求通常没什么大不了的。但是,我会回顾一下在 http 成功时调用 $state.go("^"); 是否是个好主意
  • 您能否编辑您的问题并提出您想要的最终目标/行为?您是否害怕请求被多次发出?还是您正在寻找取消请求的最佳方式?
  • @bumpy:是的,这是相关的:他们使用的 httpService 是我想到的,看起来没有明显的“更好”方式。

标签: angularjs


【解决方案1】:

也许不是最漂亮的方法,但是下面的类:

import angular from "angular";

export class HttpManager {
  constructor($scope) {
    let self = this;
    self.pendingRequests = [];
    self.nextRequestId = 0;
    $scope.$on("destroy", function () {
      self.pendingRequests.forEach(function (request) {
        request.canceler.resolve();
      });
      self.requests = [];
    })
  }
  _do(config) {
    let self = this;
    let injector = angular.injector(["ng"])
    let $q = injector.get('$q');
    let $http = injector.get('$http');
    let requestId = self.nextRequestId;
    self.nextRequestId++;
    let canceller = $q.defer();
    let cfg = angular.merge(config, { timeout: canceller.promise });
    self.pendingRequests.push({
      id: requestId,
      canceller: canceller
    });
    let requestPromise = $http(cfg);
    requestPromise.finally(function() {
      self.pendingRequests = self.pendingRequests.filter(request => request.id === requestId);
    });
    return requestPromise;
  }
  post(url, data, config) {
    return this._do(angular.merge({method: "post", url: url, data: data}, config));
  }
};

可以如下使用:

import { HttpManager } from "utils/http-manager.js"
MyController() {
  $scope.http = HttpManager($scope);
  $scope.http.post(...);
}

【讨论】:

    猜你喜欢
    • 2011-06-16
    • 1970-01-01
    • 2023-03-03
    • 2010-10-10
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多