AngularJS: প্রতিশ্রুতি কোথায় ব্যবহার করবেন?


141

আমি ফেসবুক লগইন পরিষেবাদির কয়েকটি উদাহরণ দেখেছি যা এফবি গ্রাফ এপিআই অ্যাক্সেস করার প্রতিশ্রুতি ব্যবহার করছে ।

উদাহরণ # 1 :

this.api = function(item) {
  var deferred = $q.defer();
  if (item) {
    facebook.FB.api('/' + item, function (result) {
      $rootScope.$apply(function () {
        if (angular.isUndefined(result.error)) {
          deferred.resolve(result);
        } else {
          deferred.reject(result.error);
        }
      });
    });
  }
  return deferred.promise;
}

এবং পরিষেবাগুলি "$scope.$digest() // Manual scope evaluation"যখন প্রতিক্রিয়া পেয়েছিল তখন ব্যবহৃত হয়েছিল

উদাহরণ # 2 :

angular.module('HomePageModule', []).factory('facebookConnect', function() {
    return new function() {
        this.askFacebookForAuthentication = function(fail, success) {
            FB.login(function(response) {
                if (response.authResponse) {
                    FB.api('/me', success);
                } else {
                    fail('User cancelled login or did not fully authorize.');
                }
            });
        }
    }
});

function ConnectCtrl(facebookConnect, $scope, $resource) {

    $scope.user = {}
    $scope.error = null;

    $scope.registerWithFacebook = function() {
        facebookConnect.askFacebookForAuthentication(
        function(reason) { // fail
            $scope.error = reason;
        }, function(user) { // success
            $scope.user = user
            $scope.$digest() // Manual scope evaluation
        });
    }
}

JSFiddle

প্রশ্নগুলি হ'ল:

  • উপরের উদাহরণগুলিতে পার্থক্য কী ?
  • $ Q পরিষেবাটি ব্যবহার করার কারণ এবং কেস কী ?
  • এবং এটি কিভাবে কাজ করে ?

9
শোনার মতো মনে হচ্ছে যে প্রতিশ্রুতিগুলি কী তা কেন এবং সাধারণভাবে কেন সেগুলি ব্যবহার করা উচিত ... সেগুলি কৌনিকের সাথে একচেটিয়া নয় এবং প্রচুর পরিমাণে উপলভ্য সামগ্রী রয়েছে
Charlietfl

1
@ চর্লিয়েটফ্লাল, ভাল পয়েন্ট, তবে আমি একটি জটিল উত্তর প্রত্যাশা করেছি যা উভয়ই কভার করবে: কেন তারা সাধারণভাবে ব্যবহৃত হয় এবং কীভাবে এটি কৌণিকর ক্ষেত্রে ব্যবহার করা যায়। আপনার পরামর্শের জন্য ধন্যবাদ
ম্যাকসেম

উত্তর:


401

এটি আপনার প্রশ্নের সম্পূর্ণ উত্তর হতে যাচ্ছে না, তবে আপনি যখন $qপরিষেবাতে নথিপত্র পড়ার চেষ্টা করবেন তখন আশা করি এটি আপনাকে এবং অন্যদের সহায়তা করবে । এটি বুঝতে আমার কিছুটা সময় লেগেছে।

আসুন এক মুহুর্তের জন্য অ্যাঙ্গুলারজেএস আলাদা করে রাখি এবং কেবল ফেসবুক এপিআই কলগুলি বিবেচনা করি। উভয় এপিআই কল কলব্যাককে কলবিকে অবহিত করার জন্য কল্পনা করে যখন ফেসবুকের কাছ থেকে প্রতিক্রিয়া পাওয়া যায়:

  facebook.FB.api('/' + item, function (result) {
    if (result.error) {
      // handle error
    } else {
      // handle success
    }
  });
  // program continues while request is pending
  ...

এটি জাভাস্ক্রিপ্ট এবং অন্যান্য ভাষায় অ্যাসিনক্রোনাস অপারেশন পরিচালনা করার জন্য একটি আদর্শ প্যাটার্ন।

এই প্যাটার্নের সাথে একটি বড় সমস্যা দেখা দেয় যখন আপনাকে অ্যাসিক্রোনাস অপারেশনগুলির ক্রম সম্পাদন করতে হবে, যেখানে প্রতিটি ক্রমিক ক্রিয়া পূর্ববর্তী ক্রিয়াকলাপের ফলাফলের উপর নির্ভর করে। এই কোডটি এটাই করছে:

  FB.login(function(response) {
      if (response.authResponse) {
          FB.api('/me', success);
      } else {
          fail('User cancelled login or did not fully authorize.');
      }
  });

প্রথমে এটি লগ ইন করার চেষ্টা করে এবং তারপরেই লগইন সফল হয়েছিল তা যাচাইয়ের পরে এটি গ্রাফ এপিআইতে অনুরোধ করে।

এমনকি এই ক্ষেত্রে, যা কেবল দুটি ক্রিয়াকলাপকে এক সাথে শৃঙ্খলিত করছে, জিনিসগুলি অগোছালো হতে শুরু করে। পদ্ধতিটি askFacebookForAuthenticationব্যর্থতা এবং সাফল্যের জন্য একটি কলব্যাক গ্রহণ করে, তবে FB.loginসফল হয় কিন্তু FB.apiব্যর্থ হলে কী ঘটে ? পদ্ধতির successফলাফল নির্বিশেষে এই পদ্ধতিটি সর্বদা কলব্যাকের ডাক দেয় FB.api

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

এখন, আসুন আমরা একটি মুহুর্তের জন্য ফেসবুক এপিআইকে আলাদা করে রাখি এবং কেবলমাত্র $qপরিষেবা দ্বারা প্রয়োগ করা হিসাবে কৌনিক প্রতিশ্রুতি API বিবেচনা করি । এই পরিষেবাদির দ্বারা প্রয়োগ করা প্যাটার্ন হ'ল অ্যাসিক্রোনাস প্রোগ্রামিংকে সাধারণ বিবৃতিগুলির একটি রৈখিক সিরিজের অনুরূপ কিছুতে ফিরিয়ে আনার চেষ্টা, উপায়টির কোনও ধাপে ত্রুটি 'নিক্ষেপ' করার ক্ষমতা এবং শেষে এটি হ্যান্ডেল করার মতো ক্ষমতা পরিচিত try/catchব্লক

এই স্বীকৃত উদাহরণ বিবেচনা করুন। বলুন আমাদের দুটি ফাংশন রয়েছে, যেখানে দ্বিতীয় ফাংশনটি প্রথমটির ফলাফল গ্রাস করে:

 var firstFn = function(param) {
    // do something with param
    return 'firstResult';
 };

 var secondFn = function(param) {
    // do something with param
    return 'secondResult';
 };

 secondFn(firstFn()); 

এখন কল্পনা করুন যে ফার্স্টফেন এবং সেকেন্ডফ্যান উভয়ই সম্পূর্ণ হতে দীর্ঘ সময় নেয়, তাই আমরা এই ক্রমটি অ্যাসিঙ্ক্রোনালি প্রক্রিয়া করতে চাই। প্রথমে আমরা একটি নতুন deferredঅবজেক্ট তৈরি করি , যা ক্রিয়াকলাপের প্রতিনিধিত্ব করে:

 var deferred = $q.defer();
 var promise = deferred.promise;

promiseসম্পত্তি ব্যবস্থাপনার পরিণামস্বরূপ ফলাফলের প্রতিনিধিত্ব করে। আপনি যদি কোনও প্রতিশ্রুতি তৈরির সাথে সাথে লগ করেন তবে দেখতে পাবেন যে এটি কেবল একটি খালি অবজেক্ট ( {})। এখনও দেখার মতো কিছুই নেই, ডানদিকে চলুন।

এখনও অবধি আমাদের প্রতিশ্রুতি কেবল চেইনের প্রারম্ভিক পয়েন্ট উপস্থাপন করে। এখন আমাদের দুটি অপারেশন যুক্ত করুন:

 promise = promise.then(firstFn).then(secondFn);

thenপদ্ধতি চেইন একটি পদক্ষেপ যোগ করা হয়েছে এবং তারপর নতুন প্রতিশ্রুতি বর্ধিত চেন পরিণামস্বরূপ ফলাফলের প্রতিনিধিত্বমূলক ফেরৎ। আপনি নিজের পছন্দমতো পদক্ষেপ যুক্ত করতে পারেন।

এখনও অবধি, আমরা আমাদের ক্রিয়াকলাপগুলি নির্ধারণ করেছি, তবে বাস্তবে কিছুই ঘটেনি। আপনি deferred.resolveচেইনের প্রথম আসল ধাপে যেতে চান এমন প্রাথমিক মান নির্দিষ্ট করে কল করে আপনি জিনিসগুলি শুরু করবেন :

 deferred.resolve('initial value');

এবং তারপরে ... এখনও কিছুই হয় না। মডেল পরিবর্তনগুলি যথাযথভাবে পর্যবেক্ষণ করা হয়েছে তা নিশ্চিত করার জন্য, পরের বার $applyডাকা না হওয়া পর্যন্ত কৌণিক আসলে চেইনের প্রথম পদক্ষেপটি কল করে না :

 deferred.resolve('initial value');
 $rootScope.$apply();

 // or     
 $rootScope.$apply(function() {
    deferred.resolve('initial value');
 });

সুতরাং ত্রুটি পরিচালনা সম্পর্কে কি? এখনও অবধি আমরা কেবল চেইনের প্রতিটি ধাপে একটি সাফল্য হ্যান্ডলার নির্দিষ্ট করেছি । thenএকটি ত্রুটি হ্যান্ডলারকে secondচ্ছিক দ্বিতীয় আর্গুমেন্ট হিসাবেও গ্রহণ করে। এখানে আরও একটি প্রতিশ্রুতি শৃঙ্খলার দীর্ঘ উদাহরণ, এ বার ত্রুটি পরিচালনার সাথে:

 var firstFn = function(param) {
    // do something with param
    if (param == 'bad value') {
      return $q.reject('invalid value');
    } else {
      return 'firstResult';
    }
 };

 var secondFn = function(param) {
    // do something with param
    if (param == 'bad value') {
      return $q.reject('invalid value');
    } else {
      return 'secondResult';
    }
 };

 var thirdFn = function(param) {
    // do something with param
    return 'thirdResult';
 };

 var errorFn = function(message) {
   // handle error
 };

 var deferred = $q.defer();
 var promise = deferred.promise.then(firstFn).then(secondFn).then(thirdFn, errorFn);

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

আপনার উদাহরণগুলিতে (এবং আপনার প্রশ্নসমূহ) দ্রুত ফিরে আসার জন্য, আমি কেবলই বলব যে তারা মডেল পরিবর্তনগুলি পর্যবেক্ষণের পদ্ধতিতে অ্যাঙ্গুলারের পদ্ধতিতে ফেসবুকের কলব্যাক ভিত্তিক এপিআই মানিয়ে নেওয়ার জন্য দুটি ভিন্ন উপায়ে উপস্থাপন করে। প্রথম উদাহরণটি এপিআই কলকে একটি প্রতিশ্রুতিতে আবৃত করে, যা কোনও স্কোপে যুক্ত করা যেতে পারে এবং অ্যাংুলারের টেম্প্লেটিং সিস্টেম দ্বারা বোঝা যায়। দ্বিতীয়টি সরাসরি সুযোগের উপর কলব্যাকের ফলাফল নির্ধারণের আরও নিষ্ঠুর বল প্রয়োগ করে এবং তার পরে $scope.$digest()বহিরাগত উত্স থেকে পরিবর্তন সম্পর্কে কৌণিককে সচেতন করার আহ্বান জানায় ।

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


5
আমি মনে করি এটি দুর্দান্ত উত্তর! প্রধান জিনিস, আমার জন্য, যখন সাধারণ প্রতিশ্রুতি প্রকৃত সত্য তখন সাধারণ ক্ষেত্রে বর্ণনা করছিল। সত্যিই আমি আরও একটি বাস্তব উদাহরণ আশা করছিলাম (যেমন ফেসবুকের মতো), তবে এটি আমার অনুমানের সাথেও কাজ করে। অনেক ধন্যবাদ!
ম্যাকসেম

2
একাধিক thenপদ্ধতিতে শৃঙ্খলার বিকল্প ব্যবহার করা $q.all। তার উপর একটি দ্রুত টিউটোরিয়াল এখানে পাওয়া যাবে
বোগদান

2
$q.allআপনার একাধিক স্বতন্ত্র অ্যাসিনক্রোনাস অপারেশনস সম্পূর্ণ হওয়ার জন্য অপেক্ষা করতে হবে তবে এটি উপযুক্ত । যদি প্রতিটি অপারেশন পূর্ববর্তী ক্রিয়াকলাপের ফলাফলের উপর নির্ভর করে তবে এটি চেইন প্রতিস্থাপন করে না।
কার্লগোল্ড

1
তারপরে শৃঙ্খলার বিষয়টি সংক্ষেপে ব্যাখ্যা করা হয়েছে। আমাকে এর সম্পূর্ণ সম্ভাব্যতা বুঝতে এবং ব্যবহার করতে সহায়তা করেছে। ধন্যবাদ
তুষার জোশী

1
দুর্দান্ত উত্তর @ কার্লগোলে! আমার একটা প্রশ্ন আছে. যদি, সর্বশেষ কোড স্নিপেটে, আপনি সেই return 'firstResult'অংশটি পরিবর্তন করেন তবে return $q.resolve('firstResult')কী পার্থক্য হবে?
টেকনোফাইল

9

আমি একটি জটিল উত্তর প্রত্যাশা করেছি যা উভয়ই কভার করবে: কেন তারা সাধারণভাবে ব্যবহৃত হয় এবং কীভাবে এটি কৌনিকতে ব্যবহার করা যায়

এটি কৌণিক প্রতিশ্রুতিগুলির এমভিপি (ন্যূনতম বাস্তবিক প্রতিশ্রুতি) এর জন্য উদ্দীপনা : http://plnkr.co/edit/QBAB0usWXc96TnxqKhuA?p= পূর্বরূপ

উৎস:

(লিঙ্কগুলিতে ক্লিক করতে খুব অলসদের জন্য)

index.html

  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
    <script src="app.js"></script>
  </head>

  <body ng-app="myModule" ng-controller="HelloCtrl">
    <h1>Messages</h1>
    <ul>
      <li ng-repeat="message in messages">{{ message }}</li>
    </ul>
  </body>

</html>

app.js

angular.module('myModule', [])

  .factory('HelloWorld', function($q, $timeout) {

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

      $timeout(function() {
        deferred.resolve(['Hello', 'world']);
      }, 2000);

      return deferred.promise;
    };

    return {
      getMessages: getMessages
    };

  })

  .controller('HelloCtrl', function($scope, HelloWorld) {

    $scope.messages = HelloWorld.getMessages();

  });

(আমি জানি এটি আপনার নির্দিষ্ট ফেসবুক উদাহরণটি সমাধান করে না তবে আমি নিম্নলিখিত স্নিপেটগুলি দরকারী বলে মনে করি)

ভায়া: http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/


28 ফেব্রুয়ারী 2014 আপডেট করুন: 1.2.0 হিসাবে, প্রতিশ্রুতিগুলি আর টেমপ্লেটগুলির দ্বারা সমাধান করা হয় না। http://www.benlesh.com/2013/02/angularjs-creating-service-with-http.html

(চূড়ান্ত উদাহরণ 1.1.5 ব্যবহার করে।)


আফাইক আমরা তাই ভালোবাসি কারণ আমরা অলস
এমকেবি

এটি আমাকে $ কিউ, স্থগিত এবং শৃঙ্খলাবদ্ধ বুঝতে সহায়তা করেছে function ফাংশন কল করার জন্য, তাই ধন্যবাদ।
aliopi

1

একটি বিলম্বিত একটি অ্যাসিনক্রোনিক অপারেশনের ফলাফলকে উপস্থাপন করে। এটি এমন একটি ইন্টারফেস প্রকাশ করে যা রাষ্ট্র এবং এটি প্রতিনিধিত্ব করে এমন ক্রিয়াকলাপের সিগন্যালের জন্য ব্যবহার করা যেতে পারে। এটি সম্পর্কিত প্রতিশ্রুতি উদাহরণ পাওয়ার জন্য একটি উপায়ও সরবরাহ করে।

একটি প্রতিশ্রুতি এটি সম্পর্কিত স্থগিতের সাথে কথোপকথনের জন্য একটি ইন্টারফেস সরবরাহ করে এবং তাই আগ্রহী পক্ষগুলিকে রাজ্যে অ্যাক্সেস পেতে এবং মুলতুবি করা অপারেশনের ফলাফলের অনুমতি দেয়।

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


1

একটি নিয়ামকের মধ্যে প্রতিশ্রুতি ব্যবহার করুন এবং ডেটা উপলব্ধ কিনা তা নিশ্চিত করুন

 var app = angular.module("app",[]);
      
      app.controller("test",function($scope,$q){
        var deferred = $q.defer();
        deferred.resolve("Hi");
        deferred.promise.then(function(data){
        console.log(data);    
        })
      });
      angular.bootstrap(document,["app"]);
<!DOCTYPE html>
<html>

  <head>
    <script data-require="angular.js@*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
  </head>

  <body>
    <h1>Hello Angular</h1>
    <div ng-controller="test">
    </div>
  </body>

</html>

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