আমি এই জাতীয় অনুরূপ কিছু সন্ধানে এই প্রশ্নে হোঁচট খেয়েছি, তবে আমি মনে করি এটি কী ঘটছে তার পাশাপাশি তার অতিরিক্ত কিছু সমাধানের একটি বিশদ ব্যাখ্যার প্রাপ্য।
যখন একটি কৌণিক অভিব্যক্তি এক আপনি ব্যবহার HTML এ উপস্থিত যেমন কৌণিক স্বয়ংক্রিয়ভাবে একটি সেট করে $watch
জন্য $scope.foo
, এবং যখনই এইচটিএমএল আপডেট হবে $scope.foo
পরিবর্তন।
<div ng-controller="FooCtrl">
<div ng-repeat="item in foo">{{ item }}</div>
</div>
এখানে অনির্যুক্ত সমস্যাটি হ'ল দুটি জিনিসের একটির এমনটি প্রভাবিত aService.foo
হচ্ছে যাতে পরিবর্তনগুলি সনাক্ত করা যায় না। এই দুটি সম্ভাবনা হ'ল:
aService.foo
প্রতিবার একটি নতুন অ্যারেতে সেট হয়ে যাচ্ছে, যার কারণে উল্লেখটি পুরানো হয়ে যায়।
aService.foo
এমনভাবে আপডেট করা হচ্ছে $digest
যাতে আপডেটে কোনও চক্রটি ট্রিগার না হয়।
সমস্যা 1: পুরানো রেফারেন্স
প্রথম সম্ভাবনা বিবেচনা করে, ধরে $digest
নেওয়া হচ্ছে যে প্রয়োগ করা হচ্ছে, যদি aService.foo
সর্বদা একই অ্যারে হয় তবে স্বয়ংক্রিয়ভাবে সেটটি $watch
নীচের কোড স্নিপেটে দেখানো অনুসারে পরিবর্তনগুলি সনাক্ত করবে।
সমাধান 1-এ: নিশ্চিত হন যে প্রতিটি আপডেটে অ্যারে বা অবজেক্ট একই জিনিস
angular.module('myApp', [])
.factory('aService', [
'$interval',
function($interval) {
var service = {
foo: []
};
// Create a new array on each update, appending the previous items and
// adding one new item each time
$interval(function() {
if (service.foo.length < 10) {
var newArray = []
Array.prototype.push.apply(newArray, service.foo);
newArray.push(Math.random());
service.foo = newArray;
}
}, 1000);
return service;
}
])
.factory('aService2', [
'$interval',
function($interval) {
var service = {
foo: []
};
// Keep the same array, just add new items on each update
$interval(function() {
if (service.foo.length < 10) {
service.foo.push(Math.random());
}
}, 1000);
return service;
}
])
.controller('FooCtrl', [
'$scope',
'aService',
'aService2',
function FooCtrl($scope, aService, aService2) {
$scope.foo = aService.foo;
$scope.foo2 = aService2.foo;
}
]);
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="FooCtrl">
<h1>Array changes on each update</h1>
<div ng-repeat="item in foo">{{ item }}</div>
<h1>Array is the same on each udpate</h1>
<div ng-repeat="item in foo2">{{ item }}</div>
</div>
</body>
</html>
আপনি দেখতে পাচ্ছেন, অনুমিতভাবে সংযুক্ত এনজি-রিপিট পরিবর্তন aService.foo
হওয়ার সাথে সাথে আপডেট হয় না aService.foo
, তবে এনজি-রিপিট সংযুক্ত aService2.foo
থাকে । এটি কারণ আমাদের রেফারেন্সটি aService.foo
পুরানো, তবে আমাদের রেফারেন্সটি aService2.foo
তা নয়। আমরা প্রারম্ভিক অ্যারের সাথে একটি রেফারেন্স তৈরি করেছি $scope.foo = aService.foo;
, এটি পরবর্তী আপডেটে পরিষেবা দ্বারা বাতিল করা হয়েছিল, যার অর্থ $scope.foo
আর আর আমরা চাইছি না এমন অ্যারে রেফারেন্স করা।
যাইহোক, প্রাথমিক রেফারেন্সটি কৌশলে রাখা হয়েছে তা নিশ্চিত করার বেশ কয়েকটি উপায় রয়েছে, তবে কখনও কখনও অবজেক্ট বা অ্যারে পরিবর্তন করা প্রয়োজন। বা যদি পরিষেবার সম্পত্তিটি কোনও String
বা আধ্যাত্মিক আদিম হিসাবে উল্লেখ করে Number
? এই ক্ষেত্রে, আমরা কেবল একটি রেফারেন্সের উপর নির্ভর করতে পারি না। তাহলে আমরা কী করতে পারি?
ইতিমধ্যে দেওয়া বেশ কয়েকটি উত্তর ইতিমধ্যে সেই সমস্যার কিছু সমাধান দেয়। যাইহোক, আমি ব্যক্তিগতভাবে মন্তব্যগুলিতে জিন এবং থেলওয়েজদের পরামর্শ দেওয়া সহজ পদ্ধতিটি ব্যবহারের পক্ষে :
এইচটিএমএল মার্কআপে কেবল aService.foo উল্লেখ করুন
সমাধান 1-বি: পরিষেবাতে সুযোগের সাথে সংযুক্তি করুন, এবং {service}.{property}
এইচটিএমএলে রেফারেন্স করুন।
অর্থ, কেবল এটি করুন:
এইচটিএমএল:
<div ng-controller="FooCtrl">
<div ng-repeat="item in aService.foo">{{ item }}</div>
</div>
জাতীয়:
function FooCtrl($scope, aService) {
$scope.aService = aService;
}
angular.module('myApp', [])
.factory('aService', [
'$interval',
function($interval) {
var service = {
foo: []
};
// Create a new array on each update, appending the previous items and
// adding one new item each time
$interval(function() {
if (service.foo.length < 10) {
var newArray = []
Array.prototype.push.apply(newArray, service.foo);
newArray.push(Math.random());
service.foo = newArray;
}
}, 1000);
return service;
}
])
.controller('FooCtrl', [
'$scope',
'aService',
function FooCtrl($scope, aService) {
$scope.aService = aService;
}
]);
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js@1.4.7" data-semver="1.4.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="FooCtrl">
<h1>Array changes on each update</h1>
<div ng-repeat="item in aService.foo">{{ item }}</div>
</div>
</body>
</html>
এইভাবে, প্রতিটির মধ্যে সংকল্পটি $watch
সমাধান হবে, যা সঠিকভাবে আপডেট হওয়া মান পাবে।aService.foo
$digest
আপনি নিজের কাজের সাথে যা করার চেষ্টা করছেন এটি এটির মতো, তবে উপায়টি প্রায় খুব কম। আপনি $watch
নিয়ামকটিতে একটি অপ্রয়োজনীয় যোগ করেছেন যা যখনই পরিবর্তন foo
হয় $scope
তখন স্পষ্টতই রাখে । আপনি যে অতিরিক্ত প্রয়োজন হবে না $watch
যখন আপনি সংযুক্ত aService
পরিবর্তে aService.foo
করার $scope
বেঁধে স্পষ্টভাবে, এবং aService.foo
মার্কআপ হবে।
এখন এটি বেশ ভাল এবং ধরে নিচ্ছি একটি $digest
চক্র প্রয়োগ করা হচ্ছে। উপরের আমার উদাহরণগুলিতে আমি $interval
অ্যারেগুলি আপডেট করতে অ্যাংুলার পরিষেবা ব্যবহার করেছি , যা $digest
প্রতিটি আপডেটের পরে স্বয়ংক্রিয়ভাবে একটি লুপ বন্ধ করে দেয় off তবে কী যদি পরিষেবা ভেরিয়েবলগুলি (যে কারণেই হোক না কেন) "কৌণিক বিশ্বের" ভিতরে আপডেট হচ্ছে না। অন্য কথায়, যখনই পরিষেবার সম্পত্তি পরিবর্তিত হয় তখন আমরা একটি চক্র স্বয়ংক্রিয়ভাবে সক্রিয় হয়ে উঠব না$digest
?
সমস্যা 2: অনুপস্থিত $digest
এখানকার অনেকগুলি সমাধানই এই সমস্যাটি সমাধান করবে, তবে আমি কোড হুইস্পেরারের সাথে একমত :
কেন আমরা কৌণিকের মতো কাঠামো ব্যবহার করছি তা হ'ল আমাদের নিজস্ব পর্যবেক্ষক নিদর্শনগুলি রান্না করা নয়
অতএব, আমি aService.foo
উপরের দ্বিতীয় উদাহরণে যেমন দেখিয়েছি HTML মার্কআপে রেফারেন্সটি ব্যবহার করা চালিয়ে যেতে পছন্দ করব এবং নিয়ামকের মধ্যে কোনও অতিরিক্ত কলব্যাক নিবন্ধন করতে হবে না back
সমাধান 2: এর সাথে একটি সেটার এবং গেটর ব্যবহার করুন $rootScope.$apply()
আমি অবাক হয়েছি এখনও কেউ সেটার এবং গেটর ব্যবহারের পরামর্শ দেয়নি । এই ক্ষমতাটি ECMAScript5 তে প্রবর্তিত হয়েছিল, এবং এটি এখন বছরের পর বছর ধরে রয়েছে। অবশ্যই, এর অর্থ যদি, যে কোনও কারণে, আপনাকে সত্যিকারের পুরানো ব্রাউজারগুলি সমর্থন করা দরকার, তবে এই পদ্ধতিটি কার্যকর হবে না, তবে আমার মনে হয় জাভাস্ক্রিপ্টে গেটারস এবং সেটটারগুলি বিস্তৃতভাবে নিখরচায় রয়েছে। এই বিশেষ ক্ষেত্রে, তারা বেশ কার্যকর হতে পারে:
factory('aService', [
'$rootScope',
function($rootScope) {
var realFoo = [];
var service = {
set foo(a) {
realFoo = a;
$rootScope.$apply();
},
get foo() {
return realFoo;
}
};
// ...
}
angular.module('myApp', [])
.factory('aService', [
'$rootScope',
function($rootScope) {
var realFoo = [];
var service = {
set foo(a) {
realFoo = a;
$rootScope.$apply();
},
get foo() {
return realFoo;
}
};
// Create a new array on each update, appending the previous items and
// adding one new item each time
setInterval(function() {
if (service.foo.length < 10) {
var newArray = [];
Array.prototype.push.apply(newArray, service.foo);
newArray.push(Math.random());
service.foo = newArray;
}
}, 1000);
return service;
}
])
.controller('FooCtrl', [
'$scope',
'aService',
function FooCtrl($scope, aService) {
$scope.aService = aService;
}
]);
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="FooCtrl">
<h1>Using a Getter/Setter</h1>
<div ng-repeat="item in aService.foo">{{ item }}</div>
</div>
</body>
</html>
এখানে আমি সেবা ফাংশন একটি 'ব্যক্তিগত' পরিবর্তনশীল যোগ করেছেন: realFoo
। এই পেতে আপডেট এবং ব্যবহার উদ্ধার হচ্ছে get foo()
এবং set foo()
উপর যথাক্রমে ফাংশন service
অবজেক্ট।
$rootScope.$apply()
সেট ফাংশনটির ব্যবহারটি নোট করুন । এটি নিশ্চিত করে যে কৌনিক কোনও পরিবর্তন সম্পর্কে সচেতন হবে service.foo
। আপনি যদি 'ইনগ্রোগ' ত্রুটি পান তবে এই দরকারী রেফারেন্স পৃষ্ঠাটি দেখতে পান বা আপনি কৌনিক > = 1.3 ব্যবহার করেন তবে আপনি কেবল ব্যবহার করতে পারেন $rootScope.$applyAsync()
।
এছাড়াও aService.foo
খুব ঘন ঘন আপডেট করা হয় তবে এটি থেকে সতর্ক থাকুন , যেহেতু এটি পারফরম্যান্সকে উল্লেখযোগ্যভাবে প্রভাবিত করতে পারে। পারফরম্যান্স যদি কোনও সমস্যা হয়ে থাকে তবে আপনি সেটারটি ব্যবহার করে এখানে অন্যান্য উত্তরের মতো একটি পর্যবেক্ষক প্যাটার্ন সেট আপ করতে পারেন।