programing

angularjs-app에서 ($q 사용) 모든 비동기 동작에 대한 로딩 지시자를 만드는 방법

powerit 2023. 9. 20. 20:49
반응형

angularjs-app에서 ($q 사용) 모든 비동기 동작에 대한 로딩 지시자를 만드는 방법

각 js(예: https://gist.github.com/maikeldaloo/5140733) )에서 로드 indic레이터에 대한 몇 가지 접근법이 있다는 것을 알고 있습니다.

그러나 이러한 옵션은 모든 호출에 대해 구성해야 하거나, 원하는 대로 전세계적으로 작동하는 경우에는 http-request에만 적용되지만 서비스에서 사용되는 $q-promise에는 적용되지 않습니다.

지금까지 본 글로벌 로딩 지표는

$httpProvider.responseInterceptors.push(interceptor);

이와 비슷한 것이 있습니까?$q,좋아해를$qProvider.reponseInterceptors? 만약 그렇지 않다면, 그러한 기능을 구현하는 가장 편리한 방법은 무엇일까요?예를 들어 장식가 패턴을 사용할 수 있습니까?

아주 복잡하고, 불필요하고, 아마도 부서진 것 같지만, 당신은 장식할 수 있습니다.$q그리고 그것을 무시합니다.defer기능.

누군가가 새로운 것을 요구할 때마다defer()자체 버전을 실행하고 카운터도 증가시킵니다.나눠주기 전에.deferobject, 당신은 a를 등록합니다.finally콜백(각도 1.2.0만 해당하지만)always적합할 수도 있습니다). 카운터를 축소합니다.

마지막으로 시계를 추가합니다.$rootScope이 카운터가 0보다 클 때(faster가 0보다 클 때) 모니터링합니다.pendingPromisses인에$rootScope그리고 묶는 것처럼ng-show="pendingPromisses > 0").

app.config(function($provide) {
    $provide.decorator('$q', ['$delegate', '$rootScope', function($delegate, $rootScope) {
      var pendingPromisses = 0;
      $rootScope.$watch(
        function() { return pendingPromisses > 0; }, 
        function(loading) { $rootScope.loading = loading; }
      );
      var $q = $delegate;
      var origDefer = $q.defer;
      $q.defer = function() {
        var defer = origDefer();
        pendingPromisses++;
        defer.promise.finally(function() {
          pendingPromisses--;
        });
        return defer;
      };
      return $q;
    }]);
});

그런 다음, 다음에서 상속하는 범위에 바인딩된 보기$rootScope다음을 가질 수 있습니다.

<span ng-show="loading">Loading, please wait</span>

(이것은 분리 범위가 있는 지시에서는 작동하지 않습니다.)

여기서 본방사수.

현재 안정적인 1.2.0을 위해 작동하는 공식 문서에 좋은 예가 있습니다.

http://docs.angularjs.org/api/ng.$http (페이지 상단 4분의 1, 가로채기 검색)

이 문서를 추출한 결과 다음과 같은 해결책이 도출되었습니다.

angular.module('RequestInterceptor', [])
  .config(function ($httpProvider) {
    $httpProvider.interceptors.push('requestInterceptor');
  })
  .factory('requestInterceptor', function ($q, $rootScope) {
    $rootScope.pendingRequests = 0;
    return {
           'request': function (config) {
                $rootScope.pendingRequests++;
                return config || $q.when(config);
            },

            'requestError': function(rejection) {
                $rootScope.pendingRequests--;
                return $q.reject(rejection);
            },

            'response': function(response) {
                $rootScope.pendingRequests--;
                return response || $q.when(response);
            },

            'responseError': function(rejection) {
                $rootScope.pendingRequests--;
                return $q.reject(rejection);
            }
        }
    });

그런 다음 pendingRequests > 0을 ng-show 식으로 사용할 수 있습니다.

OP의 요청에 따라 현재 작업 중인 앱에 사용하는 방법을 기준으로 합니다.이 메서드는 다음의 동작을 변경하지 않습니다.$q, 오히려 시각적 표시가 필요한 약속을 처리하기 위해 매우 간단한 API를 추가합니다.이것은 사용되는 모든 곳에서 수정이 필요하지만, 이것은 한 줄짜리일 뿐입니다.

사용.

서비스가 있습니다.ajaxIndicator, UI의 일부분을 업데이트하는 방법을 알고 있습니다.약속이 해결될 때까지 약속과 유사한 개체가 표시를 제공해야 할 때마다 다음을 사용합니다.

// $http example:
var promise = $http.get(...);
ajaxIndicator.indicate(promise); // <--- this line needs to be added

약속에 대한 참조를 유지하지 않으려면 다음을(를 수행합니다.

// $http example without keeping the reference:
ajaxIndicator.indicate($http.get(...));

또는 리소스를 사용할 경우:

var rc = $resource(...);
...
$scope.obj = rc.get(...);
ajaxIndicator.indicate($scope.obj);

에는 고정 : Angular 1.2 의, 합니다). 왜냐하면 이 작업은 수행되지 않기 때문입니다.$then()(Resource Object).

$rootScope.ajaxActive:

<div class="ajax-indicator" ng-show="ajaxActive"></div>

실행

(당사 출처에서 수정됨)경고: 이 구현은 중첩 호출을 고려하지 않습니다! (우리의 요구 사항은 UI 차단을 요구하므로 중첩 호출을 기대하지 않습니다. 관심이 있다면 이 코드를 강화할 수 있습니다.)

app.service("ajaxIndicator", ["$rootScope"], function($rootScope) {
    "use strict";

    $rootScope.ajaxActive = false;

    function indicate(promise) {
        if( !$rootScope.ajaxActive ) {
            $rootScope.ajaxActive = true;
            $rootScope.$broadcast("ajax.active"); // OPTIONAL
            if( typeof(promise) === "object" && promise !== null ) {
                if( typeof(promise.always) === "function" ) promise.always(finished);
                else if( typeof(promise.then) === "function" ) promise.then(finished,finished);
                else if( typeof(promise.$then) === "function" ) promise.$then(finished,finished);
            }
        }
    }

    function finished() {
        $rootScope.ajaxActive = false;
    }

    return {
        indicate: indicate,
        finished: finished
    };
});

몇 주 전에 똑같은 큰 질문이 있었는데 마침 작업 버튼의 로딩 상태와 ng-repeat 컨텐츠 로딩을 나타내는 몇 가지 지시를 내렸습니다.

시간을 좀 써서 github에 밀어 넣었습니다. https://github.com/ocolot/angularjs_loading_buttons

도움이 되었으면 좋겠습니다.

언급URL : https://stackoverflow.com/questions/17494732/how-to-make-a-loading-indicator-for-every-asynchronous-action-using-q-in-an-a

반응형