প্রসেসিং service HTTP প্রতিক্রিয়া পরিষেবাটিতে


233

আমি সম্প্রতি এখানে এসওতে যে সমস্যার মুখোমুখি হচ্ছি তার একটি বিশদ বিবরণ পোস্ট করেছি । যেহেতু আমি প্রকৃত $httpঅনুরোধটি প্রেরণ করতে পারি নি, ততই আমি অ্যাসিঙ্ক্রোনাস আচরণ অনুকরণের জন্য সময়সীমা ব্যবহার করেছি। আমার মডেল থেকে দেখার জন্য ডেটা বাইন্ডিংটি সঠিকভাবে কাজ করছে, @ ব্লুপির সাহায্যে

এখন, আমি যখন (স্থানীয়ভাবে পরীক্ষিত) $httpপরিবর্তে ব্যবহার করি তখন আমি $timeoutদেখতে পেতাম অ্যাসিঙ্ক্রোনাস অনুরোধটি সফল হয়েছে এবং dataআমার পরিষেবায় জেসন প্রতিক্রিয়াতে পূর্ণ। তবে, আমার দৃষ্টিভঙ্গি আপডেট হচ্ছে না।

প্লাঙ্কার আপডেট করা হয়েছে এখানে

উত্তর:


419

এখানে একটি প্লঙ্ক রয়েছে যা আপনি যা চান তা করেন: http://plnkr.co/edit/TTlbSv?p= পূর্বরূপ

ধারণাটি হ'ল যে আপনি অসম্পূর্ণভাবে ফিরে আসা প্রতিক্রিয়াগুলি পরিচালনা ও অ্যাক্সেসের জন্য সরাসরি প্রতিশ্রুতি দিয়ে এবং তাদের "তারপর" ফাংশনগুলি নিয়ে কাজ করেন।

app.factory('myService', function($http) {
  var myService = {
    async: function() {
      // $http returns a promise, which has a then function, which also returns a promise
      var promise = $http.get('test.json').then(function (response) {
        // The then function here is an opportunity to modify the response
        console.log(response);
        // The return value gets picked up by the then in the controller.
        return response.data;
      });
      // Return the promise to the controller
      return promise;
    }
  };
  return myService;
});

app.controller('MainCtrl', function( myService,$scope) {
  // Call the async method and then do stuff with what is returned inside our own then function
  myService.async().then(function(d) {
    $scope.data = d;
  });
});

এখানে একটি আরও জটিল সংস্করণ যা অনুরোধটিকে ক্যাশে করে তাই আপনি কেবল এটি প্রথমবার তৈরি করুন ( http://plnkr.co/edit/2yH1F4IMZlMS8QsV9rHv?p=preview ):

app.factory('myService', function($http) {
  var promise;
  var myService = {
    async: function() {
      if ( !promise ) {
        // $http returns a promise, which has a then function, which also returns a promise
        promise = $http.get('test.json').then(function (response) {
          // The then function here is an opportunity to modify the response
          console.log(response);
          // The return value gets picked up by the then in the controller.
          return response.data;
        });
      }
      // Return the promise to the controller
      return promise;
    }
  };
  return myService;
});

app.controller('MainCtrl', function( myService,$scope) {
  $scope.clearData = function() {
    $scope.data = {};
  };
  $scope.getData = function() {
    // Call the async method and then do stuff with what is returned inside our own then function
    myService.async().then(function(d) {
      $scope.data = d;
    });
  };
});

13
পরিষেবাটি বাধা দেওয়ার পরেও নিয়ামকটিতে সাফল্য এবং ত্রুটি পদ্ধতিগুলি কল করার কোনও উপায় আছে কি then?
andyczerwonka

2
@ পেটবিডি যদি আমি myService.async()বিভিন্ন কন্ট্রোলার থেকে আমার একাধিকবার কল করতে চাই তবে আপনি কীভাবে পরিষেবাটি সংগঠিত করবেন যাতে এটি কেবল $http.get()প্রথম অনুরোধের জন্যই হয়, এবং পরবর্তী সমস্ত অনুরোধগুলি কেবলমাত্র একটি স্থানীয় অবজেক্ট অ্যারে ফিরিয়ে দেয় যা প্রথম কলটিতে সেট হয়ে যায় myService.async()। অন্য কথায়, আমি জেএসএন পরিষেবাটিতে একাধিক, অযথা অনুরোধগুলি এড়াতে চাই, যখন সত্যই আমার কেবল একটি প্রয়োজন।
GFoley83

5
@ জিএফলে ৩৩ - এখানে যান: plnkr.co/edit/2yH1F4IMZlMS8QsV9rHv?p= পূর্বরূপ দেখুন । আপনি যদি কনসোলটি দেখেন তবে আপনি দেখতে পাবেন যে অনুরোধটি কেবল একবার করা হয়েছিল।
পিট বিডি

3
@ পেটবিডি আমি মনে করি আপনি $scope.data = myService.async()সরাসরি নিয়ামকের মধ্যেও ব্যবহার করতে পারেন ।
জুলিয়ান

2
@ ব্লোজি- আমি প্লঙ্কস আপডেট করেছি। এখানে আসলটি (1.2dCC3 এ আপডেট হয়েছে): plnkr.co/edit/3Nwxxk?p= পূর্বরূপ এখানে পরিষেবাটি ব্যবহার করা হচ্ছে: plnkr.co/edit/a993Mn?p= পূর্বরূপ
পিট বিডি

82

এটি সহজ হতে দিন। এটা যেমন সহজ

  1. promiseআপনার পরিষেবাতে ফিরে আসুন (পরিষেবাতে ব্যবহারের দরকার নেই then)
  2. thenআপনার নিয়ামক ব্যবহার করুন

ডেমো। http://plnkr.co/edit/cbdG5p?p=preview

var app = angular.module('plunker', []);

app.factory('myService', function($http) {
  return {
    async: function() {
      return $http.get('test.json');  //1. this returns promise
    }
  };
});

app.controller('MainCtrl', function( myService,$scope) {
  myService.async().then(function(d) { //2. so you can use .then()
    $scope.data = d;
  });
});

আপনার লিঙ্কে, এটি app.factoryএবং এটি আপনার কোডে app.service। এটি app.factoryএই ক্ষেত্রে অনুমিত ।
পুনরায় ক্যাপচা

1
app.service কাজ। এছাড়াও - এটি আমার কাছে সবচেয়ে মার্জিত সমাধানের মতো দেখাচ্ছে। আমি কিছু অনুপস্থিত করছি?
ব্যবহারকারী1679130

1
মনে হচ্ছে প্রতিবারই আমি একটি কৌণিক সমস্যা পেয়েছি @ অ্যালেনহউকিমের উত্তর আছে! (এই সপ্তাহের তৃতীয়
বার-

আমি কেবল স্থিতি কোড দিয়ে এখানে কীভাবে সাফল্য এবং ত্রুটি স্থাপন করব তা জানতে চাই
অনুজ

58

এটি অ্যাসিঙ্ক্রোনাস $scopeহওয়ায় এজ্যাক্স কলটি সম্পূর্ণ হওয়ার আগেই ডেটা পাচ্ছে।

আপনি $qআপনার পরিষেবাতে এটি তৈরি করতে promiseএবং এটি নিয়ামককে ফেরত দিতে ব্যবহার করতে পারেন এবং নিয়ামক then()বিপরীতে ডাকের মধ্যে ফলাফলটি পেতে পারেন promise

আপনার সেবা,

app.factory('myService', function($http, $q) {
  var deffered = $q.defer();
  var data = [];  
  var myService = {};

  myService.async = function() {
    $http.get('test.json')
    .success(function (d) {
      data = d;
      console.log(d);
      deffered.resolve();
    });
    return deffered.promise;
  };
  myService.data = function() { return data; };

  return myService;
});

তারপরে, আপনার নিয়ামকটিতে:

app.controller('MainCtrl', function( myService,$scope) {
  myService.async().then(function() {
    $scope.data = myService.data();
  });
});

2
এটি অন্যদের চেয়ে বেশি ওও হওয়ায় আমি এটি পছন্দ করি one তবে এমন কোনও কারণ আছে যা আপনি না করেন this.async = function() {এবং this.getData = function() {return data}? আমি আশা করি আপনি যা বলতে চাইছেন তা পেয়ে
সাইকেল

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

আমি যদি সঠিকভাবে বুঝতে পারি তবে deffered = $q.defer()যদি আমি মাই সার্ভিস.সেসিএনসি () কে আরও
দু'বার

1
এই উদাহরণটি একটি ক্লাসিক স্থগিত অ্যান্টি-প্যাটার্ন । সঙ্গে একটি প্রতিশ্রুতি এবং তৈয়ার থেকে কোন প্রয়োজন নেই $q.deferযেমন $httpপরিষেবা ইতিমধ্যেই একটি প্রতিশ্রুতি ফেরৎ। প্রত্যাশিত প্রতিশ্রুতি যদি $httpকোনও ত্রুটি ফিরে আসে তবে স্তব্ধ হয়ে যাবে । উপরন্তু .successএবং .errorপদ্ধতি অবচিত এবং হয়েছে AngularJS 1.6 থেকে সরানো
জর্জিউগ

23

টোশ শিমায়ামার একটি সমাধান রয়েছে তবে আপনি যদি এই সত্যটি ব্যবহার করেন যে $ এইচটিপি প্রতিশ্রুতি দেয় এবং সেই প্রতিশ্রুতিগুলির কোনও মূল্য ফিরে আসতে পারে তবে আপনি অনেকগুলি সহজ করতে পারেন:

app.factory('myService', function($http, $q) {
  myService.async = function() {
    return $http.get('test.json')
    .then(function (response) {
      var data = reponse.data;
      console.log(data);
      return data;
    });
  };

  return myService;
});

app.controller('MainCtrl', function( myService,$scope) {
  $scope.asyncData = myService.async();
  $scope.$watch('asyncData', function(asyncData) {
    if(angular.isDefined(asyncData)) {
      // Do something with the returned data, angular handle promises fine, you don't have to reassign the value to the scope if you just want to use it with angular directives
    }
  });

});

কফিস্ক্রিপ্টে একটি সামান্য বিক্ষোভ: http://plunker.no.de/edit/ksnErx?live=preview

আপনার প্লাঙ্কার আমার পদ্ধতির সাথে আপডেট হয়েছে: http://plnkr.co/edit/mwSZGK?p= পূর্বরূপ


আমি আপনার পদ্ধতির পাশাপাশি আরও চেষ্টা করব। তবে, আমি ফলাফলটি ফিরে আসার পরিবর্তে পরিষেবাতে ক্যাপচার করতে চাই। এখানে সম্পর্কিত সম্পর্কিত প্রশ্নটি stackoverflow.com/questions/12504747/… দেখুন । আমি নিয়ামকের বিভিন্ন উপায়ে $ http দ্বারা ফিরিয়ে নেওয়া ডেটা প্রক্রিয়া করতে চাই। আপনার সাহায্যের জন্য আবার ধন্যবাদ.
বিএসআর

`তুমি পরিষেবায় প্রতিশ্রুতি ব্যবহার করতে পারেন, যদি আপনি $ পছন্দ না ঘড়ি আপনি'promise.then কি করতে পারেন (ফাংশন (তথ্য); onErrorCallback {service.data = ডেটা})
Guillaume86

আমি একটি plunker পুলিশের থেকে forked যোগ
Guillaume86

1
অন্যথায় আপনি Ctrl এ $ সুযোগ ব্যবহার করতে পারেন নির্গত সেবা এবং $ সুযোগ থেকে $ $ এ আপনার নিয়ামক যে ডেটা ফিরে এসেছে বলতে কিন্তু আমি সত্যিই একটি সুবিধা দেখতে পাচ্ছি না।।
Guillaume86

7

আমার মনে হয় আরও ভাল উপায় এরকম কিছু হবে:

সার্ভিস:

app.service('FruitsManager',function($q){

    function getAllFruits(){
        var deferred = $q.defer();

        ...

        // somewhere here use: deferred.resolve(awesomeFruits);

        ...

        return deferred.promise;
    }

    return{
        getAllFruits:getAllFruits
    }

});

এবং নিয়ামক আপনি সহজেই ব্যবহার করতে পারেন:

$scope.fruits = FruitsManager.getAllFruits();

কৌণিক স্বয়ংক্রিয়ভাবে সমাধান awesomeFruitsকরা হবে $scope.fruits


4
deferred.resolve ()? আরও সুনির্দিষ্ট হন দয়া করে এবং $ HTTP কলটি কোথায়? এছাড়াও আপনি কেন একটি পরিষেবাতে কোনও জিনিস ফেরত দেন?

6

আমারও একই সমস্যা ছিল, তবে আমি যখন ইন্টারনেটে সার্ফিং করছিলাম তখন বুঝতে পেরেছিলাম $ HTTP ডিফল্টরূপে কোনও প্রতিশ্রুতি ফিরে আসে, তখন "ডেটা" ফেরার পরে আমি "তখন" দিয়ে এটি ব্যবহার করতে পারি। কোডটি দেখুন:

 app.service('myService', function($http) {
       this.getData = function(){
         var myResponseData = $http.get('test.json').then(function (response) {
            console.log(response);.
            return response.data;
          });
         return myResponseData;

       }
});    
 app.controller('MainCtrl', function( myService, $scope) {
      // Call the getData and set the response "data" in your scope.  
      myService.getData.then(function(myReponseData) {
        $scope.data = myReponseData;
      });
 });

4

আপনার অ্যারেতে ইউআইকে আবদ্ধ করার সময় আপনি দৈর্ঘ্য 0 এ সেট করে এবং ডেটাটিকে অ্যারেতে ঠেলা দিয়ে সরাসরি সেই একই অ্যারেটি আপডেট করেছেন তা নিশ্চিত করতে চাইবেন।

এর পরিবর্তে (যা আলাদা আলাদা অ্যারে রেফারেন্স সেট করে dataযার বিষয়ে আপনার ইউআই জানতে পারে না):

 myService.async = function() {
    $http.get('test.json')
    .success(function (d) {
      data = d;
    });
  };

এটা চেষ্টা কর:

 myService.async = function() {
    $http.get('test.json')
    .success(function (d) {
      data.length = 0;
      for(var i = 0; i < d.length; i++){
        data.push(d[i]);
      }
    });
  };

এখানে একটি ফ্রিডল যা নতুন অ্যারে বনাম খালি করে সেট করা এবং বিদ্যমানটিতে যোগ করার মধ্যে পার্থক্য দেখায়। আমি আপনার plnkr কাজ করতে পারিনি তবে আশা করি এটি আপনার পক্ষে কাজ করে!


যে কাজ করে না। কনসোল লগে, আমি দেখতে পেলাম সাফল্যের কলব্যাকে সঠিকভাবে আপডেট করা হয়েছে, তবে ডেটা নয়। ফাংশন ইতিমধ্যে কার্যকর করা হতে পারে।
বিএসআর

এই পদ্ধতির অবশ্যই কাজ করা উচিত সম্ভবত ডেটা ধরণের অ্যারে না হওয়ার সাথে এটির কোনও সম্পর্ক রয়েছে (উদাহরণস্বরূপ অ্যারেতে আপনাকে ডিডি অ্যাক্সেস করতে হবে)। এই plnkr দেখুন উদাহরণস্বরূপ ত্রুটির জন্য অ্যারে মধ্যে একটি স্ট্রিং ঠেলা
গ্লোপি

1
angular.copy(d, data)কাজ করবে। যখন কোনও গন্তব্য অনুলিপি () পদ্ধতিতে সরবরাহ করা হয়, তখন এটি প্রথমে গন্তব্যের উপাদানগুলি মুছবে এবং তারপরে উত্স থেকে নতুনটিতে অনুলিপি করবে।
মার্ক রাজকক

4

এর সাথে সম্পর্কিত আমিও একই ধরণের সমস্যার মধ্য দিয়ে গিয়েছিলাম, তবে অ্যাঙ্গুলার দ্বারা তৈরি বা পোস্ট দিয়ে নয় তবে একটি তৃতীয় পক্ষের দ্বারা তৈরি করা (আমার ক্ষেত্রে ক্রোম এক্সটেনশন) extension
আমি যে সমস্যার মুখোমুখি হয়েছি তা হ'ল ক্রোম এক্সটেনশানটি ফিরে আসবে না then()তাই আমি উপরের সমাধানটিতে এটি করতে পারিনি তবে ফলাফল এখনও অ্যাসিনক্রোনাস।
সুতরাং আমার সমাধানটি একটি পরিষেবা তৈরি করা এবং কলব্যাকে এগিয়ে যাওয়া

app.service('cookieInfoService', function() {
    this.getInfo = function(callback) {
        var model = {};
        chrome.cookies.get({url:serverUrl, name:'userId'}, function (response) {
            model.response= response;
            callback(model);
        });
    };
});

তারপর আমার নিয়ামক

app.controller("MyCtrl", function ($scope, cookieInfoService) {
    cookieInfoService.getInfo(function (info) {
        console.log(info);
    });
});

আশা করি এটি অন্যদের একই সমস্যা পেতে সহায়তা করতে পারে।


4

আমি পড়েছি http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/ [AngularJS সুযোগ সরাসরি একটি প্রতিশ্রুতি স্থাপন বদলে নিজে সমাধান তুলে আমাদের নিয়ামক লজিক স্ট্রিমলাইন করতে আমাদের অনুমতি দেয় সাফল্যের কলব্যাকের মান]

খুব সহজ এবং সহজ :)

var app = angular.module('myApp', []);
            app.factory('Data', function($http,$q) {
                return {
                    getData : function(){
                        var deferred = $q.defer();
                        var promise = $http.get('./largeLoad').success(function (response) {
                            deferred.resolve(response);
                        });
                        // Return the promise to the controller
                        return deferred.promise; 
                    }
                }
            });
            app.controller('FetchCtrl',function($scope,Data){
                $scope.items = Data.getData();
            });

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


কাজ করে না এর রিটার্ন মান defrred.promiseকোনও ফাংশন নয়।
জর্জেন পল

@ আনারসউন্ডারসিটি কেন এটি একটি ফাংশন হওয়ার প্রয়োজন? এটি একটি প্রতিশ্রুতি বস্তু।
শেভ

@ আনারসউন্ডারসিসি আপনার মানে কি স্থগিত এবং মুলতুবি নয়?
ডেরিক

2
PeteBD হিসাবে নির্দিষ্ট, এই ফর্মটি $scope.items = Data.getData(); Anglular মধ্যে অবচিত
poshest

2

জিনিসগুলি করার "প্রতিশ্রুতি" পদ্ধতির কারণে, service http ব্যবহার করা সেবার গ্রাহককে কীভাবে প্রতিক্রিয়াটি আনপ্যাক করবেন সে সম্পর্কে "জানতে" হবে তা সত্যই আমি পছন্দ করি না।

আমি কেবল কিছু কল করতে এবং ডেটা বের করতে চাই, পুরানো $scope.items = Data.getData();পথের অনুরূপ , যা এখন অবহেলিত

আমি কিছুক্ষণ চেষ্টা করেছি এবং একটি নিখুঁত সমাধান নিয়ে আসিনি, তবে এখানে আমার সেরা শট ( প্লাঙ্কার )। কারও কাজে লাগতে পারে।

app.factory('myService', function($http) {
  var _data;  // cache data rather than promise
  var myService = {};

  myService.getData = function(obj) { 
    if(!_data) {
      $http.get('test.json').then(function(result){
        _data = result.data;
        console.log(_data);  // prove that it executes once
        angular.extend(obj, _data);
      }); 
    } else {  
      angular.extend(obj, _data);
    }
  };

  return myService;
}); 

তারপরে নিয়ামক:

app.controller('MainCtrl', function( myService,$scope) {
  $scope.clearData = function() {
    $scope.data = Object.create(null);
  };
  $scope.getData = function() {
    $scope.clearData();  // also important: need to prepare input to getData as an object
    myService.getData($scope.data); // **important bit** pass in object you want to augment
  };
});

আমি ইতিমধ্যে ত্রুটিগুলি চিহ্নিত করতে পারি

  • আপনাকে যে বস্তুটিতে ডেটা যুক্ত করতে চান তা আপনাকে পাস করতে হবে , যা কৌণিকের কোনও স্বজ্ঞাত বা সাধারণ প্যাটার্ন নয়
  • getDataকেবলমাত্র objকোনও বস্তুর আকারে প্যারামিটারটি গ্রহণ করতে পারে (যদিও এটি কোনও অ্যারেও গ্রহণ করতে পারে), যা অনেক অ্যাপ্লিকেশনগুলির জন্য সমস্যা হবে না, তবে এটি একটি ঘোর সীমাবদ্ধতা
  • আপনি ইনপুট বস্তুর প্রস্তুত আছে $scope.dataসঙ্গে = {}এটা একটি বস্তু করতে (মূলত কি $scope.clearData()উপরে আছে), অথবা = []একটি অ্যারের, অথবা এটি কাজ করে না (আমরা ইতিমধ্যে কোন ডেটা আসছে সম্পর্কে কিছু অনুমান করা হচ্ছে) হবে। আমি এই প্রস্তুতি পদক্ষেপটি IN করার চেষ্টা করেছি getData, তবে কোনও ভাগ্য নেই।

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


1

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

App.factory('dataStorage', function($http) {
     var dataStorage;//storage for cache

     return (function() {
         // if dataStorage exists returned cached version
        return dataStorage = dataStorage || $http({
      url: 'your.json',
      method: 'GET',
      cache: true
    }).then(function (response) {

              console.log('if storage don\'t exist : ' + response);

              return response;
            });

    })();

});

এই পরিষেবাটি ক্যাশড ডেটা ফেরত দেবে বা $http.get;

 dataStorage.then(function(data) {
     $scope.data = data;
 },function(e){
    console.log('err: ' + e);
 });

0

নীচের কোড চেষ্টা করুন

আপনি নিয়ামক (পেজসিআরটিএল) এবং পরিষেবা (ডেটা সার্ভিস) বিভক্ত করতে পারেন

'use strict';
(function () {
    angular.module('myApp')
        .controller('pageContl', ['$scope', 'dataService', PageContl])
        .service('dataService', ['$q', '$http', DataService]);
    function DataService($q, $http){
        this.$q = $q;
        this.$http = $http;
        //... blob blob 
    }
    DataService.prototype = {
        getSearchData: function () {
            var deferred = this.$q.defer(); //initiating promise
            this.$http({
                method: 'POST',//GET
                url: 'test.json',
                headers: { 'Content-Type': 'application/json' }
            }).then(function(result) {
                deferred.resolve(result.data);
            },function (error) {
                deferred.reject(error);
            });
            return deferred.promise;
        },
        getABCDATA: function () {

        }
    };
    function PageContl($scope, dataService) {
        this.$scope = $scope;
        this.dataService = dataService; //injecting service Dependency in ctrl
        this.pageData = {}; //or [];
    }
    PageContl.prototype = {
         searchData: function () {
             var self = this; //we can't access 'this' of parent fn from callback or inner function, that's why assigning in temp variable
             this.dataService.getSearchData().then(function (data) {
                 self.searchData = data;
             });
         }
    }
}());

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.