sourcecode

경로 전환 시 자원 약속을 취소하는 방법을 Angularjs

codebag 2023. 2. 27. 22:49
반응형

경로 전환 시 자원 약속을 취소하는 방법을 Angularjs

Angularjs에 발을 담그는 중이야저는 약속과 관련이 있다고 생각하는 문제가 있습니다.

예를 들어, 'A' 루트를 로드하면 A의 컨트롤러를 통해 여러 개의 Ajax 요구가 발생합니다.

allSites = AllSites.query({ id:categoryID });

allSites.$promise.then(function(allSites){
    //add stuff to the scope and does other things 
    //(including making another ajax request)
});

다음으로 컨트롤러 경유로 독자적인 API 요구를 하는 루트 'B'가 있습니다.

$scope.categories = Category.query();

A번 노선에서 현재 사용하고 있는 공장 서비스는 다음과 같습니다.

.factory('AllSites',function($resource){
    return $resource('api/categorySites/:id');
});

'되기 전에 될 때까지 ()그에서 'A에서 'A'에 있는 될 때까지 ).이 완료될 때까지 기다립니다(실제로 query() 요구가 이루어지지만, 그 시점에서 A에서 온 것이 처리되지 않는 한 해결되지 않습니다..then()지금 다른 길을 가고 있기 때문에 필요없지만, 계속 일어나고 있습니다.

devtools 타임라인에서 볼 수 있듯이 녹색 선은 'B' 경로로 전환한 시기를 나타냅니다.루트 'B'에 대한 요구는 위의 두 가지 요구(통상 매우 빠른 요구)가 해결될 때까지 해결되지 않았습니다.(이 시점에서 뷰를 유저로서 사용할 수 있습니다).그 후 루트 A에서 더 많은 약속이 해결됩니다.

마이데브툴

저는 답을 찾기 위해 모든 곳을 찾아봤지만, 약속이 해결될 때까지 경로 로딩을 "지연"하려는 사람들만 찾을 수 있습니다.하지만 제 경우엔 거의 그 반대입니다.나는 그 요구를 바꿀 때 없애고 싶다.

여기 또 다른 누군가가 같은 답을 하지 못한 질문을 하고 있습니다.Angularjs 리소스 약속 거부

어떤 도움이라도 감사합니다.

선,, 는는이을 first first first를 사용해야겠다고 했습니다.$http어떤 해결책도 찾을 수 없었기 때문에$resource나 혼자서는 작동시킬 수 없었다.

http://www.bennadel.com/blog/2616-aborting-ajax-requests-using-http-and-angularjs.htm에 있는 가이드를 사용하여 @Sid의 답변을 바탕으로 공장을 다음과 같이 변화시켰습니다.

.factory('AllSites',function($http,$q){

    function getSites(categoryID) {

        // The timeout property of the http request takes a deferred value
        // that will abort the underying AJAX request if / when the deferred
        // value is resolved.
        var deferredAbort  = $q.defer();

        // Initiate the AJAX request.
        var request = $http({
            method: 'get',
            url: 'api/categorySites/'+categoryID,
            timeout: deferredAbort.promise
        });

        // Rather than returning the http-promise object, we want to pipe it
        // through another promise so that we can "unwrap" the response
        // without letting the http-transport mechansim leak out of the
        // service layer.
        var promise = request.then(
            function( response ) {
                return( response.data );
            },
            function() {
                return( $q.reject( 'Something went wrong' ) );
            }
        );

        // Now that we have the promise that we're going to return to the
        // calling context, let's augment it with the abort method. Since
        // the $http service uses a deferred value for the timeout, then
        // all we have to do here is resolve the value and AngularJS will
        // abort the underlying AJAX request.
        promise.abort = function() {
            deferredAbort.resolve();
        };

        // Since we're creating functions and passing them out of scope,
        // we're creating object references that may be hard to garbage
        // collect. As such, we can perform some clean-up once we know
        // that the requests has finished.
        promise.finally(
            function() {
                promise.abort = angular.noop;
                deferredAbort = request = promise = null;
            }
        );

        return( promise );
    }

    // Return the public API.
    return({
        getSites: getSites
    });

});

다음으로 컨트롤러(문제의 루트 'A'):

var allSitesPromise = AllSites.getSites(categoryID);

$scope.$on('$destroy',function(){
    allSitesPromise.abort();
});

allSitesPromise.then(function(allSites){
    // do stuff here with the result
}

공장이 그렇게 지저분하지 않았으면 좋겠지만, 내가 구할 수 있는 걸 가져가겠어요.하지만, 이제 다른 관련 문제가 생겼습니다. 이 문제는 약속은 취소되었지만, 다음 조치는 여전히 지연되고 있습니다.정답이 있으면 거기에 올리면 돼요.

"$resource 요청을 취소하는 방법"이라는 답변과 유사한 질문이 있습니다.

이 질문에는 정확하게 대응하지 않지만 루트 전환 시 자원 요구를 취소할 수 있는 모든 요소가 제공됩니다.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>Cancel resource</title>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular-resource.js"></script>
  <script>
angular.module("app", ["ngResource"]).
factory(
  "services",
  ["$resource", function($resource)
  {
    function resolveAction(resolve)
    {
      if (this.params)
      {
        this.timeout = this.params.timeout;
        this.params.timeout = null;
      }

      this.then = null;
      resolve(this);
    }

    return $resource(
      "http://md5.jsontest.com/",
      {},
      {
        MD5:
        {
          method: "GET",
          params: { text: null },
          then: resolveAction
        },
      });
  }]).
controller(
  "Test",
  ["services", "$q", "$timeout", function(services, $q, $timeout)
  {
    this.value = "Sample text";
    this.requestTimeout = 100;

    this.call = function()
    {
      var self = this;

      self.result = services.MD5(
      {
        text: self.value,
        timeout: $q(function(resolve)
        {
          $timeout(resolve, self.requestTimeout);
        })
      });
    }
  }]);
  </script>
</head>
<body ng-app="app" ng-controller="Test as test">
  <label>Text: <input type="text" ng-model="test.value" /></label><br/>
  <label>Timeout: <input type="text" ng-model="test.requestTimeout" /></label><br/>
  <input type="button" value="call" ng-click="test.call()"/>
  <div ng-bind="test.result.md5"></div>
</body>
</html>

구조

  1. $resource는 액션 정의, 요청 매개 변수 및 데이터를 병합하여 $syslog 요청에 대한 구성 매개 변수를 구축합니다.
  2. $syslog 요구에 전달된 config 파라미터는 약속과 같은 오브젝트로 취급되기 때문에 설정을 초기화하는 함수를 포함할 수 있습니다.
  3. 액션의 함수는 파라미터에서 Configuration으로 타임아웃 약속을 전달할 수 있습니다.

자세한 내용은 "Cancel Angularjs 리소스 요청 취소"를 참조하십시오.

게시물을 보세요.

루트 변경 시(또는 UI 라우터를 사용하는 경우 상태 변경 시) 요구를 중단하겠다는 약속을 해결할 수 있습니다.

실현하기 가장 쉬운 일은 아닐지 몰라도 효과가 있을 것 같다.

$q.reject()와의 약속을 취소합니다.이 방법이 더 간단하다고 생각합니다.

[사이트 서비스(Sites Services)]에서 선택합니다.js:

;(() => {
  app.services('SitesServices', sitesServices)
  sitesServices.$inject = ['$http', '$q']
  function sitesServices($http, $q) {

    var sitesPromise = $q.defer()
    this.getSites = () => {
      var url = 'api/sites'
      sitesPromise.reject()
      sitesPromise = $q.defer()
      $http.get(url)
        .success(sitesPromise.resolve)
        .error(sitesPromise.reject)

      return sitesPromise.promise
    }
  }
})()

SitesController.js의 경우:

;(() => {
  app.controller('SitesController', sitesControler)
  sitesControler.$inject = ['$scope', 'SitesServices']
  function sitesControler($scope, SitesServices) {
    $scope.sites = []

    $scope.getSites = () => {
      SitesServices.getSites().then(sites => {
        $scope.sites = sites
      })
    }
  }
})()

다음 문서 확인$resource나는 이 작은 아름다움의 연결고리를 찾았다.https://docs.angularjs.org/api/ng/service/$http#usage

timeout – {number|Promise}: 밀리초 단위의 타임아웃 또는 해결되면 요구를 중단하는 약속.

나는 그것을 어느 정도 성공적으로 사용해 왔다.약간 이런 느낌이에요.

export default function MyService($q, $http) {
  "ngInject";
  var service = {
    getStuff: getStuff,
  };

  let _cancelGetStuff = angular.noop;

  return service;

  function getStuff(args) {
    _cancelGetStuff(); // cancel any previous request that might be ongoing.

    let canceller = $q( resolve => { _cancelGetStuff = resolve; });

    return $http({
      method: "GET",
      url: <MYURL>
      params: args,
      timeout: canceller
    }).then(successCB, errorCB);

    function successCB (response) {
      return response.data;
    }

    function errorCB (error) {
      return $q.reject(error.data);
    }
  }
}

명심해

  1. 마지막 요청의 결과만 원하는 것으로 가정합니다.
  2. 취소된 요청이 계속 호출됩니다.successCB하지만responseundefined.
  3. 또한 errorCB를 호출할 수도 있습니다.error.status될 것이다-1요청 시간이 초과된 경우처럼요.

언급URL : https://stackoverflow.com/questions/24440177/angularjs-how-to-cancel-resource-promise-when-switching-routes

반응형