AngularJS: অ্যাসিক্রোনাস ডেটা দিয়ে পরিষেবা শুরু করুন


475

আমার একটি অ্যাঙ্গুলারজেএস পরিষেবা রয়েছে যা আমি কিছু অ্যাসিঙ্ক্রোনাস ডেটা দিয়ে শুরু করতে চাই। এটার মতো কিছু:

myModule.service('MyService', function($http) {
    var myData = null;

    $http.get('data.json').success(function (data) {
        myData = data;
    });

    return {
        setData: function (data) {
            myData = data;
        },
        doStuff: function () {
            return myData.getSomeData();
        }
    };
});

স্পষ্টতই এটি কাজ করবে না কারণ যদি কিছু ফিরে আসার doStuff()আগে কল করার চেষ্টা করে তবে myDataআমি নাল পয়েন্টার ব্যতিক্রম পাব। যতদূর আমি এখানে জিজ্ঞাসা করা অন্যান্য প্রশ্নগুলির কয়েকটি পড়তে বলতে পারি এবং এখানে আমার কাছে কয়েকটি বিকল্প রয়েছে তবে এগুলির কোনওটিই খুব পরিষ্কার মনে হয় না (সম্ভবত আমি কিছু মিস করছি):

"রান" দিয়ে সেটআপ পরিষেবা

আমার অ্যাপটি সেট আপ করার সময় এটি করুন:

myApp.run(function ($http, MyService) {
    $http.get('data.json').success(function (data) {
        MyService.setData(data);
    });
});

তারপরে আমার পরিষেবাটি দেখতে এই রকম হবে:

myModule.service('MyService', function() {
    var myData = null;
    return {
        setData: function (data) {
            myData = data;
        },
        doStuff: function () {
            return myData.getSomeData();
        }
    };
});

এটি কিছু সময় কাজ করে তবে অ্যাসিনক্রোনাস ডেটা যদি সবকিছু শুরু করার চেয়ে বেশি সময় নেয় তবে আমি কল করলে নাল পয়েন্টার ব্যতিক্রম পাই I doStuff()

প্রতিশ্রুতি বস্তু ব্যবহার করুন

এটি সম্ভবত কাজ করবে। আমি যেখানেই মাই সার্ভিসকে কল করি তার একমাত্র নেতিবাচক দিকটি আমাকে জানতে হবে যে ডস্ট স্টাফ () একটি প্রতিশ্রুতি দেয় এবং সমস্ত কোড আমাদের thenকাছে প্রতিশ্রুতির সাথে যোগাযোগ করতে হবে । আমি বরং আমার অ্যাপ্লিকেশনটি লোড করার আগে আমার ডেটা ফিরে না আসা পর্যন্ত অপেক্ষা করব।

ম্যানুয়াল বুটস্ট্র্যাপ

angular.element(document).ready(function() {
    $.getJSON("data.json", function (data) {
       // can't initialize the data here because the service doesn't exist yet
       angular.bootstrap(document);
       // too late to initialize here because something may have already
       // tried to call doStuff() and would have got a null pointer exception
    });
});

গ্লোবাল জাভাস্ক্রিপ্ট ভার আমি আমার জেএসএনকে সরাসরি বৈশ্বিক জাভাস্ক্রিপ্ট ভেরিয়েবলে প্রেরণ করতে পারি:

এইচটিএমএল:

<script type="text/javascript" src="data.js"></script>

data.js:

var dataForMyService = { 
// myData here
};

তারপরে এটি আরম্ভ করার সময় উপলব্ধ হবে MyService:

myModule.service('MyService', function() {
    var myData = dataForMyService;
    return {
        doStuff: function () {
            return myData.getSomeData();
        }
    };
});

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

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


কৌণিক - বুটস্ট্র্যাপ একটি সার্ভার থেকে ডেটা টানতে $http, তারপরে কোনও পরিষেবাতে ডেটা সংরক্ষণ করতে, তারপরে কোনও অ্যাপ্লিকেশন বুটস্ট্র্যাপ করে অবিচ্ছিন্নভাবে কোডের মধ্য দিয়ে চলে ।
স্টিভেন ওয়েক্সলার

উত্তর:


327

আপনি একবার তাকান আছে $routeProvider.when('/path',{ resolve:{...}? এটি প্রতিশ্রুতির পদ্ধতিকে কিছুটা পরিষ্কার করতে পারে:

আপনার সেবার প্রতিশ্রুতি প্রকাশ করুন:

app.service('MyService', function($http) {
    var myData = null;

    var promise = $http.get('data.json').success(function (data) {
      myData = data;
    });

    return {
      promise:promise,
      setData: function (data) {
          myData = data;
      },
      doStuff: function () {
          return myData;//.getSomeData();
      }
    };
});

যোগ resolveআপনার রুট কনফিগ করুন:

app.config(function($routeProvider){
  $routeProvider
    .when('/',{controller:'MainCtrl',
    template:'<div>From MyService:<pre>{{data | json}}</pre></div>',
    resolve:{
      'MyServiceData':function(MyService){
        // MyServiceData will also be injectable in your controller, if you don't want this you could create a new promise with the $q service
        return MyService.promise;
      }
    }})
  }):

সমস্ত নির্ভরতা সমাধান হওয়ার আগে আপনার নিয়ামক তাত্ক্ষণিক হবেন না:

app.controller('MainCtrl', function($scope,MyService) {
  console.log('Promise is now resolved: '+MyService.doStuff().data)
  $scope.data = MyService.doStuff();
});

আমি plnkr এ একটি উদাহরণ তৈরি করেছি: http://plnkr.co/edit/GKg21XH0RwCMEQGUdZKH?p= পূর্বরূপ


1
আপনার প্রতিক্রিয়ার জন্য আপনাকে অনেক ধন্যবাদ! এটি আমার পক্ষে কাজ করবে যদি আমার মাই সার্ভিস ব্যবহার করে এমন মীমাংসার মানচিত্রে ইতিমধ্যে কোনও পরিষেবা না থাকে। আমি আমার পরিস্থিতি নিয়ে আপনার প্লঙ্কার আপডেট করেছি: plnkr.co/edit/465Cupaf5mtxljCl5NuF?p=preview । মাই সার্ভিসটি আরম্ভ করার জন্য মাইওথার সার্ভিসেসের অপেক্ষা করার কোনও উপায় আছে কি?
টেস্টিং 123

2
আমার ধারণা আমি মায়োথার সার্ভিসে প্রতিশ্রুতিগুলি শৃঙ্খল করবো - আমি শৃঙ্খলাবদ্ধ এবং কিছু মন্তব্য দিয়ে প্লাঙ্কার আপডেট করেছি - এটি কেমন দেখাচ্ছে? plnkr.co/edit/Z7dWVNA9P44Q72sLiPjW?p= পূর্বরূপ
joakimbl

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

43
এখানে একটি প্রশ্ন - আপনি কীভাবে resolveকোনও নিয়ামককে সম্পত্তি বরাদ্দ করবেন যা উল্লিখিত নেই $routeProvider। উদাহরণস্বরূপ <div ng-controller="IndexCtrl"></div>,। এখানে, নিয়ামক স্পষ্টভাবে উল্লেখ করা হয়েছে এবং রাউটিংয়ের মাধ্যমে লোড করা হয়নি। এই জাতীয় ক্ষেত্রে, তখন কেউ কন্ট্রোলারের তাত্ক্ষণিকতায় কীভাবে বিলম্ব করবে?
কলমেকাট্টি

19
উম্মম আপনি যদি রাউটিং ব্যবহার না করেন? এটি প্রায় বলার মতোই যদি আপনি রাউটিং ব্যবহার না করেন তবে আপনি অ্যাসিনক্রোনাস ডেটা সহ কৌনিক অ্যাপটি লিখতে পারবেন না। কোনও অ্যাপ্লিকেশনে ডেটা পাওয়ার প্রস্তাবিত উপায় হ'ল এটি অবিচ্ছিন্নভাবে লোড করা, তবে যত তাড়াতাড়ি আপনার একাধিক নিয়ামক রয়েছে এবং আপনি পরিষেবাগুলিতে নিক্ষেপ করছেন, বুম এটি অসম্ভব।
ওয়্যারড_ইন

88

মার্টিন অ্যাটকিন্সের সমাধানের ভিত্তিতে, এখানে একটি সম্পূর্ণ, সংক্ষিপ্ত খাঁটি-কৌণিক সমাধান:

(function() {
  var initInjector = angular.injector(['ng']);
  var $http = initInjector.get('$http');
  $http.get('/config.json').then(
    function (response) {
      angular.module('config', []).constant('CONFIG', response.data);

      angular.element(document).ready(function() {
          angular.bootstrap(document, ['myApp']);
        });
    }
  );
})();

এই সমাধানটি $ http পরিষেবাটি পেতে, কনফিগার করার অনুরোধ করে এবং যখন এটি উপলব্ধ হয় তখন এটি একটি ধ্রুবক CONFIG এ ইনজেকশন দেওয়ার জন্য একটি স্ব-সম্পাদনকারী বেনামি ফাংশন ব্যবহার করে।

একবার সম্পূর্ণরূপে, ডকুমেন্টটি প্রস্তুত না হওয়া পর্যন্ত আমরা অপেক্ষা করি এবং তারপরে অ্যাংুলার অ্যাপটি বুটস্ট্র্যাপ করি।

এটি মার্টিনের সমাধানের তুলনায় সামান্য বর্ধন, যা ডকুমেন্টটি প্রস্তুত না হওয়া অবধি কনফিগার আনতে পিছনে। আমি যতদূর জানি, এর জন্য $ http কলটি বিলম্ব করার কোনও কারণ নেই।

অংশ পরিক্ষাকরণ

দ্রষ্টব্য: আমি আবিষ্কার করেছি যে কোডটি আপনার app.jsফাইলে অন্তর্ভুক্ত করার পরে ইউনিট-টেস্টিংয়ের সময় এই সমাধানটি ভাল কাজ করে না । এর কারণ হ'ল জেএস ফাইলটি লোড হওয়ার সাথে সাথে উপরের কোডটি তত্ক্ষণাত্ চালিত হয়। এর অর্থ পরীক্ষার কাঠামো (আমার ক্ষেত্রে জুঁই) এর মক বাস্তবায়ন করার সুযোগ নেই $http

আমার সমাধান, যা আমি পুরোপুরি সন্তুষ্ট নই, এই কোডটি আমাদের index.htmlফাইলে সরিয়ে নেওয়া ছিল , যাতে গ্রান্ট / কর্ম / জেসমিন ইউনিট পরীক্ষার অবকাঠামো এটি দেখতে পায় না।


1
'বৈশ্বিক সুযোগকে দূষিত করবেন না' এর মতো বিধিগুলি কেবলমাত্র আমাদের কোডটি আরও ভাল (কম জটিল, আরও রক্ষণাবেক্ষণযোগ্য, আরও সুরক্ষিত ইত্যাদি) তৈরি করা উচিত। একক গ্লোবাল ভেরিয়েবলে কেবল ডেটা লোড করার চেয়ে এই সমাধানটি কীভাবে ভাল তা আমি দেখতে পাচ্ছি না। আমি কী মিস করছি?
ডেভিড004

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

1
আমি কৌনিক নবাগত, আমি আমার অ্যাপ্লিকেশনে কনফিগার মডিউল নির্ভরতা কীভাবে সমাধান করেছি সে সম্পর্কে এখানে কিছু নোট রয়েছে: gist.github.com/dsulli99/0be3e80db9b21ce7b989 संदर्भ : টিউটোরিয়াল.জেনকোভ.আঙ্গুলারজেস / এই সমাধানের জন্য আপনাকে ধন্যবাদ।
ডিপিএস

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

49

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

resolveরুটগুলিতে ব্যবহার করাও কোনও বিকল্প ছিল না কারণ আমার অ্যাপ্লিকেশন শুরু হওয়ার সাথে সাথে এমনকি module.config()ব্লকগুলিতেও আমার কাছে মানগুলি ধ্রুবক হিসাবে উপলব্ধ হওয়ার দরকার ছিল ।

আমি একটি ছোট অ্যাঙ্গুলারজেএস অ্যাপ তৈরি করেছি যা কনফিগারেশন লোড করে, তাদেরকে আসল অ্যাপে স্থির হিসাবে সেট করে এবং এটি বুটস্ট্র্যাপ করে।

// define the module of your app
angular.module('MyApp', []);

// define the module of the bootstrap app
var bootstrapModule = angular.module('bootstrapModule', []);

// the bootstrapper service loads the config and bootstraps the specified app
bootstrapModule.factory('bootstrapper', function ($http, $log, $q) {
  return {
    bootstrap: function (appName) {
      var deferred = $q.defer();

      $http.get('/some/url')
        .success(function (config) {
          // set all returned values as constants on the app...
          var myApp = angular.module(appName);
          angular.forEach(config, function(value, key){
            myApp.constant(key, value);
          });
          // ...and bootstrap the actual app.
          angular.bootstrap(document, [appName]);
          deferred.resolve();
        })
        .error(function () {
          $log.warn('Could not initialize application, configuration could not be loaded.');
          deferred.reject();
        });

      return deferred.promise;
    }
  };
});

// create a div which is used as the root of the bootstrap app
var appContainer = document.createElement('div');

// in run() function you can now use the bootstrapper service and shutdown the bootstrapping app after initialization of your actual app
bootstrapModule.run(function (bootstrapper) {

  bootstrapper.bootstrap('MyApp').then(function () {
    // removing the container will destroy the bootstrap app
    appContainer.remove();
  });

});

// make sure the DOM is fully loaded before bootstrapping.
angular.element(document).ready(function() {
  angular.bootstrap(appContainer, ['bootstrapModule']);
});

এটি এখানে কর্মের $timeoutপরিবর্তে (এর পরিবর্তে ব্যবহার করে দেখুন $http): http://plnkr.co/edit/FYznxP3xe8dxzwxs37hi?p= পূর্বরূপ দেখুন

হালনাগাদ

আমি নীচে মার্টিন অ্যাটকিনস এবং জেবিসিপি দ্বারা বর্ণিত পদ্ধতিটি ব্যবহার করার পরামর্শ দেব।

আপডেট 2

একাধিক প্রকল্পে আমার এটির প্রয়োজন হওয়ার কারণে, আমি কেবল একটি বোর মডিউল প্রকাশ করেছি যা এটির যত্ন নেয়: https://github.com/phPLd/angular-deferred-bootstrap

ব্যাক-এন্ড থেকে ডেটা লোড করে এবং AngularJS মডিউলে APP_CONFIG নামক একটি ধ্রুবক সেট করে এমন উদাহরণ:

deferredBootstrapper.bootstrap({
  element: document.body,
  module: 'MyApp',
  resolve: {
    APP_CONFIG: function ($http) {
      return $http.get('/api/demo-config');
    }
  }
});

11
deferredBootstrapper যেতে উপায়
fatlinesofcode

44

"ম্যানুয়াল বুটস্ট্র্যাপ" কেস বুটস্ট্র্যাপের আগে ম্যানুয়ালি ইনজেক্টর তৈরি করে কৌণিক পরিষেবাগুলিতে অ্যাক্সেস অর্জন করতে পারে। এই প্রাথমিক ইনজেক্টরটি একা দাঁড়িয়ে থাকবে (কোনও উপাদানগুলির সাথে সংযুক্ত হবে না) এবং লোড হওয়া মডিউলগুলির কেবলমাত্র একটি উপসেট অন্তর্ভুক্ত করবে। আপনার যা যা দরকার তা হ'ল মূল কৌণিক পরিষেবাদি, এটি কেবল ngএইরকম লোড করার পক্ষে যথেষ্ট :

angular.element(document).ready(
    function() {
        var initInjector = angular.injector(['ng']);
        var $http = initInjector.get('$http');
        $http.get('/config.json').then(
            function (response) {
               var config = response.data;
               // Add additional services/constants/variables to your app,
               // and then finally bootstrap it:
               angular.bootstrap(document, ['myApp']);
            }
        );
    }
);

উদাহরণস্বরূপ, module.constantআপনি আপনার অ্যাপ্লিকেশনটিতে ডেটা উপলব্ধ করার জন্য প্রক্রিয়াটি ব্যবহার করতে পারেন:

myApp.constant('myAppConfig', data);

এটি myAppConfigএখন অন্য যে কোনও পরিষেবার মতোই ইনজেকশনের ব্যবস্থা করা যেতে পারে এবং বিশেষত এটি কনফিগারেশন পর্যায়ে পাওয়া যায়:

myApp.config(
    function (myAppConfig, someService) {
        someService.config(myAppConfig.someServiceConfig);
    }
);

বা, একটি ছোট অ্যাপ্লিকেশনটির জন্য, আপনি কেবল অ্যাপ্লিকেশন জুড়ে কনফিগারেশন ফর্ম্যাট সম্পর্কে জ্ঞান ছড়িয়ে দেওয়ার ব্যয়ে গ্লোবাল কনফিগারেশনটি সরাসরি আপনার পরিষেবাতে ইনজেক্ট করতে পারেন।

অবশ্যই, যেহেতু এখানে অ্যাসিঙ্ক অপারেশনগুলি অ্যাপ্লিকেশনটির বুটস্ট্র্যাপটি ব্লক করবে এবং এইভাবে টেমপ্লেটের সংকলন / লিঙ্কিং ব্লক করবে, ng-cloakকাজকর্মের সময় অপসংশ্লিষ্ট টেমপ্লেটটি প্রদর্শিত হতে বাধা দেওয়ার জন্য নির্দেশিকাটি ব্যবহার করা বুদ্ধিমানের কাজ। আপনি ডিওএমে কিছু ধরণের লোডিং ইঙ্গিতও সরবরাহ করতে পারেন, এমন কিছু HTML সরবরাহ করে যা কেবলমাত্র AngularJS আরম্ভ না হওয়া অবধি প্রদর্শিত হবে:

<div ng-if="initialLoad">
    <!-- initialLoad never gets set, so this div vanishes as soon as Angular is done compiling -->
    <p>Loading the app.....</p>
</div>
<div ng-cloak>
    <!-- ng-cloak attribute is removed once the app is done bootstrapping -->
    <p>Done loading the app!</p>
</div>

আমি Plunker এ এই পদ্ধতির একটি সম্পূর্ণ, কার্যকারী উদাহরণ তৈরি করেছি, উদাহরণ হিসাবে একটি স্ট্যাটিক JSON ফাইল থেকে কনফিগারেশন লোড করছি।


আমি মনে করি না ডকুমেন্টটি প্রস্তুত না হওয়া অবধি আপনার $ http.get () স্থগিত করা দরকার।
জেবিসিপি

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

2
আমি আপনার পদ্ধতির সাহায্যে একটি ধনুক
ফিলিপড

@ মার্টিন অ্যাটকিনস, আমি সবেমাত্র পেয়েছি যে আপনার দুর্দান্ত পদ্ধতি অ্যাঙ্গুলার ভি 1.1 + এর সাথে কাজ করে না। দেখে মনে হচ্ছে অ্যাঙ্গুলারের প্রাথমিক সংস্করণগুলি অ্যাপ্লিকেশন বুটস্ট্র্যাপ না করা অবধি কেবল "তখন" বুঝতে পারে না। আপনার প্লঙ্কে এটি দেখতে কোড. angularjs.org/1.1.5/angular.min.js
ভেলম্যান

16

আমার একই সমস্যা ছিল: আমি resolveবিষয়টিকে ভালবাসি , তবে এটি কেবল এনজি-ভিউয়ের সামগ্রীর জন্য কাজ করে। আপনার যদি কন্ট্রোলার থাকে (শীর্ষ স্তরের নাভির জন্য, বলুন) যা এনজি-ভিউর বাইরে রয়েছে এবং যা রাউটিংটি শুরু হওয়ার আগেই ডেটা দিয়ে শুরু করা দরকার? কেবলমাত্র সেই কাজটি করার জন্য আমরা কীভাবে সার্ভার-সাইডে আশপাশ ঘটাতে পারি?

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

উদাহরণ:

//First, we have to create the angular module, because all the other JS files are going to load while we're getting data and bootstrapping, and they need to be able to attach to it.
var MyApp = angular.module('MyApp', ['dependency1', 'dependency2']);

// Use angular's version of document.ready() just to make extra-sure DOM is fully 
// loaded before you bootstrap. This is probably optional, given that the async 
// data call will probably take significantly longer than DOM load. YMMV.
// Has the added virtue of keeping your XHR junk out of global scope. 
angular.element(document).ready(function() {

    //first, we create the callback that will fire after the data is down
    function xhrCallback() {
        var myData = this.responseText; // the XHR output

        // here's where we attach a constant containing the API data to our app 
        // module. Don't forget to parse JSON, which `$http` normally does for you.
        MyApp.constant('NavData', JSON.parse(myData));

        // now, perform any other final configuration of your angular module.
        MyApp.config(['$routeProvider', function ($routeProvider) {
            $routeProvider
              .when('/someroute', {configs})
              .otherwise({redirectTo: '/someroute'});
          }]);

        // And last, bootstrap the app. Be sure to remove `ng-app` from your index.html.
        angular.bootstrap(document, ['NYSP']);
    };

    //here, the basic mechanics of the XHR, which you can customize.
    var oReq = new XMLHttpRequest();
    oReq.onload = xhrCallback;
    oReq.open("get", "/api/overview", true); // your specific API URL
    oReq.send();
})

এখন, আপনার NavDataধ্রুবক বিদ্যমান। এগিয়ে যান এবং একটি নিয়ামক বা পরিষেবা ইনজেক্ট করুন:

angular.module('MyApp')
    .controller('NavCtrl', ['NavData', function (NavData) {
        $scope.localObject = NavData; //now it's addressable in your templates 
}]);

অবশ্যই, একটি খালি এক্সএইচআর অবজেক্ট ব্যবহার করে জ্যাকুয়ারি $httpআপনার জন্য যত্ন নেবে এমন বেশ কয়েকটি চমকপ্রদ বৈশিষ্ট্য দূরে সরিয়ে দেয় , তবে এই উদাহরণটি কোনও বিশেষ নির্ভরতার সাথে কাজ করে না, অন্তত একটি সাধারণ জন্য get। আপনি যদি আপনার অনুরোধটির জন্য আরও কিছুটা শক্তি চান তবে আপনাকে সাহায্য করার জন্য একটি বাহ্যিক লাইব্রেরি লোড করুন। তবে আমি মনে করি $httpনা এই প্রসঙ্গে কৌনিক বা অন্যান্য সরঞ্জামগুলি অ্যাক্সেস করা সম্ভব ।

(এসও সম্পর্কিত পোস্ট )


8

আপনি যা করতে পারেন তা অ্যাপ্লিকেশনটির জন্য আপনার কনফিগে হ'ল রুটটির জন্য রেজোলিউশন অবজেক্টটি তৈরি করুন এবং ফাংশন পাসে $ q (প্রতিশ্রুতি অবজেক্ট) এবং আপনি যে পরিষেবাটির উপর নির্ভর করছেন তার নাম এবং সেই প্রতিশ্রুতিটি সমাধান করুন পরিষেবাটিতে $ HTTP এর জন্য কলব্যাক ফাংশন:

রুট কনফিগ

app.config(function($routeProvider){
    $routeProvider
     .when('/',{
          templateUrl: 'home.html',
          controller: 'homeCtrl',
          resolve:function($q,MyService) {
                //create the defer variable and pass it to our service
                var defer = $q.defer();
                MyService.fetchData(defer);
                //this will only return when the promise
                //has been resolved. MyService is going to
                //do that for us
                return defer.promise;
          }
      })
}

কৌণিক টেম্পলেটটি রেন্ডার বা নিয়ামককে উপলব্ধ না করা অবধি নিয়ামককে উপলব্ধ করবে না until আমরা আমাদের সেবায় এটি করতে পারি:

সেবা

app.service('MyService',function($http){
       var MyService = {};
       //our service accepts a promise object which 
       //it will resolve on behalf of the calling function
       MyService.fetchData = function(q) {
             $http({method:'GET',url:'data.php'}).success(function(data){
                 MyService.data = data;
                 //when the following is called it will
                 //release the calling function. in this
                 //case it's the resolve function in our
                 //route config
                 q.resolve();
             }
       }

       return MyService;
});

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

নিয়ামক

  app.controller('homeCtrl',function($scope,MyService){
       $scope.servicedata = MyService.data;
  });

এখন নিয়ন্ত্রকের সুযোগে আমাদের সমস্ত বাঁধাই মাই সার্ভিস থেকে উদ্ভূত ডেটা ব্যবহার করতে সক্ষম হবে।


আমার আরও সময় পেলে আমি এটি শট দেব। এটি এনজিএমডিউলগুলিতে অন্যরা যা করার চেষ্টা করেছিল তার সাথে একই দেখাচ্ছে।
টেস্টিং 123

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

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

1
@ ডেভিড এটাই আমি লক্ষ্য রেখেছিলাম, তবে আমার সমাধান-ব্লকগুলি পুনরায় না বলেই কেবল "এই সমস্ত জিনিস প্রথমে নিয়ে আসা যাক কোন রুটটি বোঝাই হচ্ছে" প্রথমে বলার যদি উপায় থাকে তবে আমি বেশি পছন্দ করব। তাদের সবার কিছু নির্ভর করে যা তারা নির্ভর করে। তবে এটি কোনও বিশাল চুক্তি নয়, এটি আরও কিছুটা অনুভূত হবে DRY :)
ivarni

2
এই পথেই আমি যাত্রা করে শেষ করেছিলাম, তবে resolveকোনও সম্পত্তি হ'ল ফাংশন হিসাবে আমার কোনও বস্তু তৈরি করতে হবে except সুতরাং এটি শেষ হয়েছেresolve:{ dataFetch: function(){ // call function here } }
aron.duby

5

সুতরাং আমি একটি সমাধান খুঁজে পেয়েছি। আমি একটি কৌণিক জেএস পরিষেবা তৈরি করেছি, আমরা এটিকে মাইডাটারোপোসিটিরি বলব এবং আমি এটির জন্য একটি মডিউল তৈরি করেছি। আমি তখন আমার সার্ভার-সাইড নিয়ামক থেকে এই জাভাস্ক্রিপ্ট ফাইলটি পরিবেশন করছি:

এইচটিএমএল:

<script src="path/myData.js"></script>

সার্ভার-সাইড:

@RequestMapping(value="path/myData.js", method=RequestMethod.GET)
public ResponseEntity<String> getMyDataRepositoryJS()
{
    // Populate data that I need into a Map
    Map<String, String> myData = new HashMap<String,String>();
    ...
    // Use Jackson to convert it to JSON
    ObjectMapper mapper = new ObjectMapper();
    String myDataStr = mapper.writeValueAsString(myData);

    // Then create a String that is my javascript file
    String myJS = "'use strict';" +
    "(function() {" +
    "var myDataModule = angular.module('myApp.myData', []);" +
    "myDataModule.service('MyDataRepository', function() {" +
        "var myData = "+myDataStr+";" +
        "return {" +
            "getData: function () {" +
                "return myData;" +
            "}" +
        "}" +
    "});" +
    "})();"

    // Now send it to the client:
    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.add("Content-Type", "text/javascript");
    return new ResponseEntity<String>(myJS , responseHeaders, HttpStatus.OK);
}

তারপরে আমি যেখানে আমার এটির প্রয়োজন হবে সেখানে আমার ডেটাআরপোসিটোরি ইনজেকশন করতে পারি:

someOtherModule.service('MyOtherService', function(MyDataRepository) {
    var myData = MyDataRepository.getData();
    // Do what you have to do...
}

এটি আমার পক্ষে দুর্দান্ত কাজ করেছে, তবে কারও কাছে যদি আমি থাকে তবে আমি কোনও প্রতিক্রিয়া জানাতে প্রস্তুত। }


আমি আপনার মডুলার পদ্ধতির পছন্দ। আমি খুঁজে পেয়েছি যে request রুটস্কোপ পরিষেবাটি অনুরোধ করার ডেটাতে উপলভ্য এবং আপনি data http.succe কলব্যাক এ ডেটা বরাদ্দ করতে পারেন। তবে, অ-গ্লোবাল আইটেমগুলির জন্য $ রুটস্কোপ ব্যবহার করা গন্ধ তৈরি করে এবং সত্যই নিয়ন্ত্রণকারী $ সুযোগকে ডেটা বরাদ্দ করা উচিত। দুর্ভাগ্যক্রমে, আমি মনে করি আপনার উদ্ভাবনী, যদিও আদর্শটি আদর্শ নয় (যদিও আপনার পক্ষে কাজ করে এমন কিছু আবিষ্কার করার জন্য সম্মান করুন)। আমি নিশ্চিত যে এখানে অবশ্যই কোনও ক্লায়েন্ট-সাইডের উত্তর থাকতে হবে যা কোনওভাবে ডেটার জন্য অপেক্ষা করে এবং সুযোগটি অ্যাসাইনমেন্টের অনুমতি দেয়। অনুসন্ধান চালিয়ে যাচ্ছে!
শিশির

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

2

এছাড়াও, আপনি প্রকৃত নিয়ন্ত্রণকারীদের মৃত্যুদন্ড কার্যকর করার আগে বিশ্বব্যাপী আপনার পরিষেবাটি সরবরাহ করতে নিম্নলিখিত কৌশলগুলি ব্যবহার করতে পারেন: https://stackoverflow.com/a/27050497/1056679 । কেবলমাত্র বিশ্বব্যাপী আপনার ডেটা সমাধান করুন এবং তারপরে এটি runব্লকে আপনার পরিষেবাতে দিন ।


1

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

আপনি এইচটিএমএল দেখতে পাবেন:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script>

function MyService {
  this.getData = function(){
    return   MyService.data;
  }
}
MyService.setData = function(data) {
  MyService.data = data;
}

angular.module('main')
.service('MyService', MyService)

</script>
<script src="/some_data.php?jsonp=MyService.setData"></script>

-1

কোনও প্রাথমিককরণ এনজি-আরআর ডিরেক্টরি ব্যবহার করার সহজ উপায়।

আপনি এনজি-ডিভ ডিভ স্কোপটি যেখানে আপনি আরআর ডেটা আনতে চান ঠিক তেমন রাখুন

index.html

<div class="frame" ng-init="init()">
    <div class="bit-1">
      <div class="field p-r">
        <label ng-show="regi_step2.address" class="show-hide c-t-1 ng-hide" style="">Country</label>
        <select class="form-control w-100" ng-model="country" name="country" id="country" ng-options="item.name for item in countries" ng-change="stateChanged()" >
        </select>
        <textarea class="form-control w-100" ng-model="regi_step2.address" placeholder="Address" name="address" id="address" ng-required="true" style=""></textarea>
      </div>
    </div>
  </div>

index.js

$scope.init=function(){
    $http({method:'GET',url:'/countries/countries.json'}).success(function(data){
      alert();
           $scope.countries = data;
    });
  };

দ্রষ্টব্য: আপনার যদি একই কোড না থাকে তবে এক জায়গায় আপনি এই পদ্ধতিটি ব্যবহার করতে পারেন।


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