AngularJS এ একটি $ http অনুরোধ বাতিল কিভাবে?




promise angular-promise (6)

AngularJS একটি অ্যাজাক্স অনুরোধ দেওয়া

$http.get("/backend/").success(callback);

অন্য অনুরোধটি চালু হলে অনুরোধটি বাতিল করার সবচেয়ে কার্যকর উপায় কী কী (একই ব্যাকেন্ড, উদাহরণস্বরূপ বিভিন্ন পরামিতি)।


আপনি একটি "সজ্জাকারী" ব্যবহার করে $http পরিষেবাতে একটি কাস্টম ফাংশন যোগ করতে পারেন যা আপনার প্রতিশ্রুতিতে abort() ফাংশন যোগ করবে।

এখানে কিছু কাজ কোড আছে:

app.config(function($provide) {
    $provide.decorator('$http', function $logDecorator($delegate, $q) {
        $delegate.with_abort = function(options) {
            let abort_defer = $q.defer();
            let new_options = angular.copy(options);
            new_options.timeout = abort_defer.promise;
            let do_throw_error = false;

            let http_promise = $delegate(new_options).then(
                response => response, 
                error => {
                    if(do_throw_error) return $q.reject(error);
                    return $q(() => null); // prevent promise chain propagation
                });

            let real_then = http_promise.then;
            let then_function = function () { 
                return mod_promise(real_then.apply(this, arguments)); 
            };

            function mod_promise(promise) {
                promise.then = then_function;
                promise.abort = (do_throw_error_param = false) => {
                    do_throw_error = do_throw_error_param;
                    abort_defer.resolve();
                };
                return promise;
            }

            return mod_promise(http_promise);
        }

        return $delegate;
    });
});

এই কোডটি $http পরিষেবাতে with_abort() ফাংশন যোগ করার জন্য angularjs এর শোভাকর কার্যকারিতা ব্যবহার করে।

with_abort() $http টাইমআউট বিকল্পটি ব্যবহার করে যা আপনাকে একটি HTTP অনুরোধ বাতিল করতে দেয়।

ফেরত প্রতিশ্রুতি একটি abort() ফাংশন অন্তর্ভুক্ত সংশোধন করা হয়। এটি শৃঙ্খলা প্রতিশ্রুতিবদ্ধ এমনকি যদি abort() কাজ করে তা নিশ্চিত করার জন্য কোড আছে।

আপনি এটি ব্যবহার করবেন কিভাবে একটি উদাহরণ এখানে:

// your original code
$http({ method: 'GET', url: '/names' }).then(names => {
    do_something(names));
});

// new code with ability to abort
var promise = $http.with_abort({ method: 'GET', url: '/names' }).then(
    function(names) {
        do_something(names));
    });

promise.abort(); // if you want to abort

ডিফল্টরূপে আপনি যখন কলটি abort() অনুরোধটি বাতিল হয়ে যায় এবং প্রতিশ্রুতির কোনও হ্যান্ডলার চালায় না।

যদি আপনি আপনার ত্রুটির হ্যান্ডলারকে abort(true) করতে চান বলে abort(true)

আপনার ত্রুটি হ্যান্ডলারের মধ্যে আপনি "ত্রুটি" xhrStatus সম্পত্তিটি পরীক্ষা করে "বাতিল" করার কারণে কিনা তা পরীক্ষা করতে পারেন। এখানে একটি উদাহরণ:

var promise = $http.with_abort({ method: 'GET', url: '/names' }).then(
    function(names) {
        do_something(names));
    }, 
    function(error) {
        if (er.xhrStatus === "abort") return;
    });

আপনি যদি UI- রাউটারের সাথে stateChangeStart এ মুলতুবি অনুরোধ বাতিল করতে চান তবে আপনি এটির মতো কিছু ব্যবহার করতে পারেন:

// সেবা

                var deferred = $q.defer();
                var scope = this;
                $http.get(URL, {timeout : deferred.promise, cancel : deferred}).success(function(data){
                    //do something
                    deferred.resolve(dataUsage);
                }).error(function(){
                    deferred.reject();
                });
                return deferred.promise;

// UIrouter কনফিগ মধ্যে //

$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
    //To cancel pending request when change state
       angular.forEach($http.pendingRequests, function(request) {
          if (request.cancel && request.timeout) {
             request.cancel.resolve();
          }
       });
    });

এখানে একটি সংস্করণ যা একাধিক অনুরোধ পরিচালনা করে, ত্রুটি ব্লকের ত্রুটিগুলি দমন করার জন্য কলব্যাকে বাতিল হওয়া স্থিতি চেক করে। (টাইপcript)

নিয়ামক স্তর:

    requests = new Map<string, ng.IDeferred<{}>>();

আমার http পেতে:

    getSomething(): void {
        let url = '/api/someaction';
        this.cancel(url); // cancel if this url is in progress

        var req = this.$q.defer();
        this.requests.set(url, req);
        let config: ng.IRequestShortcutConfig = {
            params: { id: someId}
            , timeout: req.promise   // <--- promise to trigger cancellation
        };

        this.$http.post(url, this.getPayload(), config).then(
            promiseValue => this.updateEditor(promiseValue.data as IEditor),
            reason => {
                // if legitimate exception, show error in UI
                if (!this.isCancelled(req)) {
                    this.showError(url, reason)
                }
            },
        ).finally(() => { });
    }

সাহায্যকারী পদ্ধতি

    cancel(url: string) {
        this.requests.forEach((req,key) => {
            if (key == url)
                req.resolve('cancelled');
        });
        this.requests.delete(url);
    }

    isCancelled(req: ng.IDeferred<{}>) {
        var p = req.promise as any; // as any because typings are missing $$state
        return p.$$state && p.$$state.value == 'cancelled';
    }

এখন নেটওয়ার্ক ট্যাব এ খুঁজছেন, আমি দেখতে যে এটি beatuifully কাজ করে। আমি 4 বার পদ্ধতিটি আহ্বান করেছি এবং শুধুমাত্র শেষের মধ্য দিয়ে গিয়েছিলাম।


এটি নিম্নোক্তভাবে নিম্নোক্ত পদ্ধতির সাথে $ http পরিষেবা সাজানোর দ্বারা গৃহীত উত্তরটি বাড়ায় ...

'use strict';
angular.module('admin')
  .config(["$provide", function ($provide) {

$provide.decorator('$http', ["$delegate", "$q", function ($delegate, $q) {
  var getFn = $delegate.get;
  var cancelerMap = {};

  function getCancelerKey(method, url) {
    var formattedMethod = method.toLowerCase();
    var formattedUrl = encodeURI(url).toLowerCase().split("?")[0];
    return formattedMethod + "~" + formattedUrl;
  }

  $delegate.get = function () {
    var cancelerKey, canceler, method;
    var args = [].slice.call(arguments);
    var url = args[0];
    var config = args[1] || {};
    if (config.timeout == null) {
      method = "GET";
      cancelerKey = getCancelerKey(method, url);
      canceler = $q.defer();
      cancelerMap[cancelerKey] = canceler;
      config.timeout = canceler.promise;
      args[1] = config;
    }
    return getFn.apply(null, args);
  };

  $delegate.abort = function (request) {
    console.log("aborting");
    var cancelerKey, canceler;
    cancelerKey = getCancelerKey(request.method, request.url);
    canceler = cancelerMap[cancelerKey];

    if (canceler != null) {
      console.log("aborting", cancelerKey);

      if (request.timeout != null && typeof request.timeout !== "number") {

        canceler.resolve();
        delete cancelerMap[cancelerKey];
      }
    }
  };

  return $delegate;
}]);
  }]);

এই কোডটি কি করছে?

একটি অনুরোধ বাতিল করতে "প্রতিশ্রুতি" সময়সীমা সেট করা আবশ্যক। যদি HTTP অনুরোধে কোনও সময়সীমা সেট না থাকে তবে কোডটি "প্রতিশ্রুতি" টাইমআউট যোগ করে। (যদি একটি টাইমআউট ইতিমধ্যে সেট করা হয় তবে কিছুই পরিবর্তিত হয়)।

যাইহোক, প্রতিশ্রুতি সমাধানের জন্য আমাদের "বিলম্বিত" একটি হ্যান্ডেল প্রয়োজন। আমরা এইভাবে একটি মানচিত্র ব্যবহার করি যাতে আমরা পরে "বিলম্বিত" পুনরুদ্ধার করতে পারি। আমরা যখন বর্জন পদ্ধতিটি কল করি, তখন "বিলম্বিত" মানচিত্র থেকে পুনরুদ্ধার করা হয় এবং তারপরে আমরা HTTP অনুরোধটি বাতিল করার সমাধান পদ্ধতিটি কল করি।

এই কেউ সাহায্য করে আশা করি।

সীমাবদ্ধতা

বর্তমানে এটি শুধুমাত্র $ http.get এর জন্য কাজ করে তবে আপনি $ http.post এর জন্য কোড যুক্ত করতে পারেন

ব্যবহারবিধি ...

আপনি এটি ব্যবহার করতে পারেন, উদাহরণস্বরূপ, রাষ্ট্র পরিবর্তন, নিম্নরূপ ...

rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
  angular.forEach($http.pendingRequests, function (request) {
        $http.abort(request);
    });
  });

টাইমআউট সম্পত্তির সাথে কৌণিক $ http অ্যাজাক্স বাতিল করা 1.3.15 এ কাজ করে না। এটির জন্য স্থির থাকার জন্য অপেক্ষা করতে না পারার জন্য আমি কৌণিকের মধ্যে আবৃত একটি jQuery অ্যাজাক্স সমাধান ভাগ করছি।

সমাধান দুটি সেবা জড়িত:

  • HttpService (jQuery অ্যাজাক্স ফাংশন কাছাকাছি একটি মোড়ক);
  • PendingRequestsService (মুলতুবি / খোলা Ajax অনুরোধ ট্র্যাক)

এখানে PendingRequestsService পরিষেবা যায়:

    (function (angular) {
    'use strict';
    var app = angular.module('app');
    app.service('PendingRequestsService', ["$log", function ($log) {            
        var $this = this;
        var pending = [];
        $this.add = function (request) {
            pending.push(request);
        };
        $this.remove = function (request) {
            pending = _.filter(pending, function (p) {
                return p.url !== request;
            });
        };
        $this.cancelAll = function () {
            angular.forEach(pending, function (p) {
                p.xhr.abort();
                p.deferred.reject();
            });
            pending.length = 0;
        };
    }]);})(window.angular);

Http পরিষেবা সেবা:

     (function (angular) {
        'use strict';
        var app = angular.module('app');
        app.service('HttpService', ['$http', '$q', "$log", 'PendingRequestsService', function ($http, $q, $log, pendingRequests) {
            this.post = function (url, params) {
                var deferred = $q.defer();
                var xhr = $.ASI.callMethod({
                    url: url,
                    data: params,
                    error: function() {
                        $log.log("ajax error");
                    }
                });
                pendingRequests.add({
                    url: url,
                    xhr: xhr,
                    deferred: deferred
                });            
                xhr.done(function (data, textStatus, jqXhr) {                                    
                        deferred.resolve(data);
                    })
                    .fail(function (jqXhr, textStatus, errorThrown) {
                        deferred.reject(errorThrown);
                    }).always(function (dataOrjqXhr, textStatus, jqXhrErrorThrown) {
                        //Once a request has failed or succeeded, remove it from the pending list
                        pendingRequests.remove(url);
                    });
                return deferred.promise;
            }
        }]);
    })(window.angular);

পরে আপনি যখন আপনার ডেটা লোড করছেন তখন আপনার পরিষেবাতে আপনি $ http পরিবর্তে HttpService ব্যবহার করবেন:

(function (angular) {

    angular.module('app').service('dataService', ["HttpService", function (httpService) {

        this.getResources = function (params) {

            return httpService.post('/serverMethod', { param: params });

        };
    }]);

})(window.angular);

পরে আপনার কোডটিতে আপনি তথ্য লোড করতে চান:

(function (angular) {

var app = angular.module('app');

app.controller('YourController', ["DataService", "PendingRequestsService", function (httpService, pendingRequestsService) {

    dataService
    .getResources(params)
    .then(function (data) {    
    // do stuff    
    });    

    ...

    // later that day cancel requests    
    pendingRequestsService.cancelAll();
}]);

})(window.angular);

$http দিয়ে জারি করা অনুরোধ বাতিলকরণ AngularJS এর ​​বর্তমান সংস্করণের সাথে সমর্থিত নয়। এই ক্ষমতা যোগ করার জন্য একটি টুকরা অনুরোধ খোলা আছে তবে এই PR এর পর্যালোচনা করা হয়নি তাই এটি AngularJS কোরের মধ্যে এটি তৈরি করা হবে কিনা তা স্পষ্ট নয়।







cancellation