অ্যাঙ্গুলারজেএস-এ কীভাবে একটি $ HTTP অনুরোধ বাতিল করবেন?


190

অ্যাঙ্গুলারজেএস-এ একটি অ্যাজাক্স অনুরোধ দেওয়া হয়েছে

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

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


8
নীচের উত্তরের কোনও উত্তরই অনুরোধটি নিজেই বাতিল করে দেয়। এইচটিটিপি অনুরোধটি ব্রাউজারটি ছাড়ার পরে বাতিল করার কোনও উপায় নেই। নীচের সমস্ত উত্তরগুলি কেবল কোনও উপায়ে শ্রোতাকে আবদ্ধ করে। এইচটিটিপি অনুরোধটি এখনও সার্ভারকে হিট করে, এখনও প্রক্রিয়াজাত হয় এবং সার্ভারটি এখনও একটি প্রতিক্রিয়া প্রেরণ করবে, ক্লায়েন্ট এখনও সেই প্রতিক্রিয়াটির জন্য অপেক্ষা করছে বা না করছে এটি কেবলমাত্র একটি ঘটনা।
লিয়াম



@ লিয়াম আমার প্রশ্নটি সার্ভারে বাতিল হচ্ছে না। এটি আপনার সার্ভার প্রযুক্তি / বাস্তবায়ন কী তার সাথে খুব নির্দিষ্ট হবে। আমি কলব্যাকটি পরিত্যাগের সাথে উদ্বিগ্ন ছিলাম
সোনিক সোল

উত্তর:


326

টাইমআউট প্যারামিটারের মাধ্যমে এই বৈশিষ্ট্যটি 1.1.5 রিলিজে যুক্ত করা হয়েছিল :

var canceler = $q.defer();
$http.get('/someUrl', {timeout: canceler.promise}).success(successCallback);
// later...
canceler.resolve();  // Aborts the $http request if it isn't finished.

13
প্রতিশ্রুতি দিয়ে সময়সীমা এবং ম্যানুয়াল উভয়ই বাতিল করার ক্ষেত্রে আমার কী করা উচিত?
রমন চোদিকা

15
@ রমনচোডাকা আপনি একটি প্রতিশ্রুতি দিয়ে উভয়ই করতে পারেন; আপনি জাভাস্ক্রিপ্টের নেটিভ setTimeoutফাংশন বা অ্যাংুলার এর $timeoutপরিষেবা দিয়ে কিছু সময়ের পরে প্রতিশ্রুতি বাতিল করতে একটি সময়সীমা নির্ধারণ করতে পারেন ।
কুইন স্ট্রহল

9
বাতিল করুন। সমাধান () ভবিষ্যতের অনুরোধগুলি বাতিল করবে। এটি একটি আরও ভাল সমাধান: odetocode.com/blogs/scott/archive/2014/04/24/…
টুলকিট

7
বেন নাদেল থেকে আরও সম্পূর্ণ সমাধানের আর একটি ভাল উদাহরণ: bennadel.com/blog/…
পিট

3
সত্যিই কাজ করে না। আপনি একটি কাজের নমুনা প্রদান করতে পারেন?
এডওয়ার্ড ওলামিসান

10

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

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

  • এইচটিপিএস সার্ভিস (jQuery আজাক্স ফাংশন জুড়ে একটি মোড়ক);
  • মুলতুবি রক্ষণাবেক্ষণ সার্ভিস (মুলতুবি থাকা / খোলা অ্যাজাক্স অনুরোধগুলি সন্ধান করে)

এখানে মুলতুবি রক্ষণাবেক্ষণ পরিষেবাটি যায়:

    (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);

এইচটিপি সার্ভিস পরিষেবা:

     (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 এর পরিবর্তে $ HTTP ব্যবহার করবেন:

(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);

9

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


পিআর প্রত্যাখ্যান করা হয়েছিল, ওপি এখানে একটি আপডেট জমা দিয়েছেন github.com/angular/angular.js/pull/1836
মার্ক নাদিগ

এবং সেটিও বন্ধ ছিল।
ফ্রেপন্টিলো 2

এর একটি সংস্করণ এটি হিসাবে অবতরণ করেছে । চূড়ান্ত সংস্করণটি ব্যবহার করতে সিনট্যাক্সটি বের করার চেষ্টা করছে। জনগণের নমুনাগুলি নিয়ে আসুন! :)
সিম্পলজি

'ব্যবহার' এর কৌণিক ডকুমেন্টেশন পৃষ্ঠা ডকস.আঙ্গুলারজস.আর.পি.আই / জং / সার্ভিস / এচটিটিপি একটি সময়সীমা নির্ধারণের বর্ণনা দেয় এবং কোন বস্তুগুলি (একটি প্রতিশ্রুতি) গৃহীত হয় তাও উল্লেখ করে।
ইগোর লিনো

6

আপনি যদি ইউআই-রাউটার দিয়ে স্টেট চ্যাঞ্জস্টার্টে মুলতুবি থাকা অনুরোধগুলি বাতিল করতে চান, আপনি এই জাতীয় কিছু ব্যবহার করতে পারেন:

// সেবা

                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;

// ইউআইআউটার কনফিগারেশনে

$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();
          }
       });
    });

এটি আমার পক্ষে কাজ করেছে - খুব সহজ এবং আমি কলটির নামকরণের জন্য আরও একটি যুক্ত করেছি যাতে আমি কলটি নির্বাচন করতে পারি এবং কেবলমাত্র কয়েকটি কল বাতিল করতে পারি
সাইমন ড্রাগসবাইক

ইউআই রাউটার কনফিগারেশন কেন উপস্থিত আছে তা জানতে হবে request.timeout?
ট্রাইসিস

6

কোনও কারণে কনফিগ.টাইমআউট আমার পক্ষে কাজ করে না। আমি এই পদ্ধতির ব্যবহার করেছি:

let cancelRequest = $q.defer();
let cancelPromise = cancelRequest.promise;

let httpPromise = $http.get(...);

$q.race({ cancelPromise, httpPromise })
    .then(function (result) {
...
});

এবং বাতিলকরণের জন্য বাতিল করুন। সমাধান করুন ()। আসলে এটি কোনও অনুরোধ বাতিল করে না তবে আপনি কমপক্ষে অপ্রয়োজনীয় প্রতিক্রিয়া পাবেন না।

আশাকরি এটা সাহায্য করবে.


আপনি কি আপনার সিনট্যাক্স এরর দেখেছেন { cancelPromise, httpPromise }?
মফিফটোফিলস

এটি ES6 সিনট্যাক্স, আপনি চেষ্টা করতে পারেন: সি: বাতিলপ্রোম, এইচ: HTTPPromise}
Aliaksandr Hmyrak

আমি দেখছি, অবজেক্ট শর্টনাইটায়ালাইজার
মেফিজটোফিলস

3

এটি ab 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
এখানে কোডটি ডিফার অবজেক্টগুলির জন্য রেফারেন্সগুলি বজায় রাখে যাতে ডিফার অবজেক্টটি একটি গর্ভপাত বন্ধ করার জন্য পরে সেগুলি পুনরুদ্ধার করা যায়। অনুসন্ধানের সাথে গুরুত্বপূর্ণ জিনিসটি হ'ল কী: মান জোড়া। মান হ'ল মুলতুবি বস্তু। অনুরোধ পদ্ধতি / url এর উপর ভিত্তি করে কীটি তৈরি করা একটি স্ট্রিং। আমি অনুমান করছি যে আপনি একই পদ্ধতি / url- এ একাধিক অনুরোধ বাতিল করে দিচ্ছেন। এর কারণে সমস্ত কীগুলি অভিন্ন এবং তারা মানচিত্রে একে অপরকে ওভাররাইট করে। আপনাকে মূল প্রজন্মের যুক্তিটি টুইঙ্ক করতে হবে যাতে ইউআরএল / পদ্ধতি একই রকম হলেও একটি অনন্য তৈরি করা যায়।
danday74

1
উপরের থেকে অবিরত ... এটি কোডে কোনও ত্রুটি নয়, কোডটি একাধিক অনুরোধ বাতিল করতে পরিচালিত করে ... তবে কোডটি কখনও কখনও একই url এ একই HTTP পদ্ধতিটি ব্যবহার করে একাধিক অনুরোধ রোধ করার বিষয়টি বোঝায় না ... তবে আপনি যদি লজিকটি টুইট করেন তবে আপনার এটি মোটামুটি সহজেই কাজ করতে সক্ষম হওয়া উচিত।
danday74

1
আপনাকে অনেক ধন্যবাদ! আমি একই url তে একাধিক অনুরোধ করেছিলাম কিন্তু বিভিন্ন পরামিতি সহ, এবং আপনি এই কথাটি বলার পরে আমি সেই লাইনটি পরিবর্তন করেছি এবং এটি একটি কবজির মতো কাজ করেছে!
মিগুয়েল ট্রাবাজো

1

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

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

    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';
    }

এখন নেটওয়ার্ক ট্যাবটি দেখছি, আমি দেখতে পাচ্ছি এটি মারাত্মকভাবে কাজ করে। আমি পদ্ধতিটি 4 বার কল করেছি এবং কেবল সর্বশেষটিটি পেরেছে।

এখানে চিত্র বর্ণনা লিখুন


req.resolve ( 'বাতিল করা হয়েছে'); আমার জন্য কাজ করছে না, আমি 1.7.2 সংস্করণ ব্যবহার করছি। এমনকি আমি যদি আবার কল হয় এবং প্রথম কলটি এখনও স্থগিত অবস্থায় থাকে তবে কোনও কল বাতিল করতে চাই। সাহায্য করুন. আমি সর্বদা একই ইউআরএল-এর সমস্ত মুলতুবি এপি বাতিল করে নতুন কল করা কল সরবরাহ করতে চাই
সুদর্শন কালেব্রে

1

আপনি $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;
    });
});

এই কোডটি পরিষেবাতে কোনও with_abort()ক্রিয়াকলাপ যোগ করতে কৌণিক নকশাকার কার্যকারিতা ব্যবহার করে $http

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)

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

var promise = $http.with_abort({ method: 'GET', url: '/names' }).then(
    function(names) {
        do_something(names));
    }, 
    function(error) {
        if (er.xhrStatus === "abort") return;
    });
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.