ভূমিকা
একটি বিপ্লব আসছে। জাভাস্ক্রিপ্টে একটি নতুন সংযোজন রয়েছে যা ডেটা-বাইন্ডিং সম্পর্কে আপনি যা জানেন বলে মনে করেন তার সবকিছু পরিবর্তন করতে চলেছে। এটি পরিবর্তন করতে যাচ্ছে যে কতগুলি আপনার MVC লাইব্রেরি সম্পাদনা এবং আপডেটের জন্য মডেলগুলি পর্যবেক্ষণ করে। আপনি কি সম্পত্তি পর্যবেক্ষণের বিষয়ে যত্নশীল অ্যাপগুলিতে কিছু মিষ্টি কর্মক্ষমতা বৃদ্ধির জন্য প্রস্তুত?
ঠিক আছে। ঠিক আছে। আর দেরি না করে, আমি ঘোষণা করতে পেরে খুশি যে Object.observe()
Chrome 36 স্ট্যাবলে অবতরণ করেছে। [উওওওও ভিড় বন্য হয়] .
Object.observe()
, ভবিষ্যতের ECMAScript স্ট্যান্ডার্ডের অংশ, একটি পৃথক লাইব্রেরির প্রয়োজন ছাড়াই জাভাস্ক্রিপ্ট অবজেক্টের পরিবর্তনগুলি অ্যাসিঙ্ক্রোনাসভাবে পর্যবেক্ষণ করার একটি পদ্ধতি। এটি একজন পর্যবেক্ষককে পরিবর্তনের রেকর্ডের একটি সময়-অনুযায়ী ক্রম প্রাপ্ত করার অনুমতি দেয় যা পর্যবেক্ষিত বস্তুর সেটে সংঘটিত পরিবর্তনের সেট বর্ণনা করে।
// Let's say we have a model with data
var model = {};
// Which we then observe
Object.observe(model, function(changes){
// This asynchronous callback runs
changes.forEach(function(change) {
// Letting us know what changed
console.log(change.type, change.name, change.oldValue);
});
});
যে কোনো সময় পরিবর্তন করা হয়, এটি রিপোর্ট করা হয়:
Object.observe()
(আমি এটিকে Oo() বা Oooooooo বলতে চাই), আপনি ফ্রেমওয়ার্কের প্রয়োজন ছাড়াই দ্বি-মুখী ডেটা-বাইন্ডিং প্রয়োগ করতে পারেন।
এর মানে এই নয় যে আপনি একটি ব্যবহার করবেন না। জটিল ব্যবসায়িক যুক্তি সহ বড় প্রকল্পগুলির জন্য, মতামতযুক্ত ফ্রেমওয়ার্কগুলি অমূল্য এবং আপনার সেগুলি ব্যবহার করা চালিয়ে যাওয়া উচিত। তারা নতুন ডেভেলপারদের অভিযোজন সহজ করে, কম কোড রক্ষণাবেক্ষণের প্রয়োজন এবং সাধারণ কাজগুলি কীভাবে অর্জন করা যায় তার উপর নিদর্শন আরোপ করে। যখন আপনার একটির প্রয়োজন হয় না, আপনি পলিমারের মতো ছোট, আরও ফোকাসড লাইব্রেরি ব্যবহার করতে পারেন (যা ইতিমধ্যে Oo() এর সুবিধা গ্রহণ করে)।
এমনকি যদি আপনি নিজেকে একটি ফ্রেমওয়ার্ক বা MV* লাইব্রেরি খুব বেশি ব্যবহার করে দেখেন, Oo() একই API বজায় রেখে দ্রুত, সহজ বাস্তবায়ন সহ তাদের কিছু স্বাস্থ্যকর কর্মক্ষমতা উন্নতি প্রদান করার সম্ভাবনা রয়েছে। উদাহরণস্বরূপ, গত বছর অ্যাঙ্গুলার দেখেছিল যে একটি বেঞ্চমার্কে যেখানে একটি মডেলে পরিবর্তন করা হচ্ছে, নোংরা-চেকিং প্রতি আপডেটে 40ms সময় নেয় এবং Oo() প্রতি আপডেটে 1-2ms নেয় (20-40x দ্রুত উন্নতি)।
অনেক জটিল কোডের প্রয়োজন ছাড়াই ডেটা-বাইন্ডিং এর মানে হল যে আপনাকে আর পরিবর্তনের জন্য পোল করতে হবে না, তাই আর ব্যাটারি লাইফ!
যদি আপনি ইতিমধ্যেই Oo(এ) বিক্রি হয়ে থাকেন, তাহলে বৈশিষ্ট্য পরিচিতিতে এড়িয়ে যান, অথবা এটি যে সমস্যার সমাধান করে সে সম্পর্কে আরও জানতে পড়ুন।
আমরা কি পর্যবেক্ষণ করতে চাই?
যখন আমরা ডেটা পর্যবেক্ষণ সম্পর্কে কথা বলি, তখন আমরা সাধারণত কিছু নির্দিষ্ট ধরণের পরিবর্তনের জন্য নজর রাখার কথা উল্লেখ করি:
- কাঁচা জাভাস্ক্রিপ্ট বস্তুর পরিবর্তন
- যখন বৈশিষ্ট্যগুলি যোগ করা হয়, পরিবর্তিত হয়, মুছে ফেলা হয়
- যখন অ্যারেগুলিতে উপাদানগুলি তাদের মধ্যে এবং বাইরে বিভক্ত থাকে
- বস্তুর প্রোটোটাইপ পরিবর্তন
ডেটা-বাইন্ডিংয়ের গুরুত্ব
আপনি যখন মডেল-ভিউ কন্ট্রোল সেপারেশনের বিষয়ে যত্নবান হন তখন ডেটা-বাইন্ডিং গুরুত্বপূর্ণ হয়ে উঠতে শুরু করে। এইচটিএমএল একটি মহান ঘোষণামূলক প্রক্রিয়া, কিন্তু এটি সম্পূর্ণরূপে স্থির। আদর্শভাবে, আপনি শুধু আপনার ডেটা এবং DOM-এর মধ্যে সম্পর্ক ঘোষণা করতে চান এবং DOM-কে আপ টু ডেট রাখতে চান। এটি লিভারেজ তৈরি করে এবং সত্যিই পুনরাবৃত্তিমূলক কোড লিখতে আপনার অনেক সময় বাঁচায় যা আপনার অ্যাপ্লিকেশনের অভ্যন্তরীণ অবস্থা বা সার্ভারের মধ্যে DOM-এ এবং থেকে ডেটা পাঠায়।
ডেটা-বাইন্ডিং বিশেষভাবে উপযোগী হয় যখন আপনার একটি জটিল ইউজার-ইন্টারফেস থাকে যেখানে আপনাকে আপনার ভিউয়ের একাধিক উপাদানের সাথে আপনার ডেটা মডেলের একাধিক বৈশিষ্ট্যের মধ্যে সম্পর্ক স্থাপন করতে হবে। আমরা আজ যে একক-পৃষ্ঠার অ্যাপ্লিকেশন তৈরি করছি তাতে এটি বেশ সাধারণ।
ব্রাউজারে নেটিভলি ডেটা পর্যবেক্ষণ করার উপায় বেক করে, আমরা জাভাস্ক্রিপ্ট ফ্রেমওয়ার্ক (এবং আপনার লেখা ছোট ইউটিলিটি লাইব্রেরিগুলি) দিয়ে থাকি যা বিশ্বের কিছু ধীরগতির হ্যাকগুলির উপর নির্ভর না করে মডেল ডেটাতে পরিবর্তনগুলি পর্যবেক্ষণ করার একটি উপায়।
পৃথিবী আজ কেমন দেখাচ্ছে
ডার্টি-চেকিং
আপনি আগে ডেটা-বাইন্ডিং কোথায় দেখেছেন? ঠিক আছে, আপনি যদি আপনার ওয়েবঅ্যাপ তৈরির জন্য একটি আধুনিক MV* লাইব্রেরি ব্যবহার করেন (যেমন কৌণিক, নকআউট) আপনি সম্ভবত DOM-এ মডেল ডেটা বাঁধাই করতে অভ্যস্ত। রিফ্রেশার হিসাবে, এখানে একটি ফোন তালিকা অ্যাপের উদাহরণ দেওয়া হল যেখানে আমরা একটি phones
অ্যারেতে (জাভাস্ক্রিপ্টে সংজ্ঞায়িত) প্রতিটি ফোনের মানকে একটি তালিকা আইটেমের সাথে আবদ্ধ করছি যাতে আমাদের ডেটা এবং UI সর্বদা সিঙ্ক থাকে:
<html ng-app>
<head>
...
<script src='angular.js'></script>
<script src='controller.js'></script>
</head>
<body ng-controller='PhoneListCtrl'>
<ul>
<li ng-repeat='phone in phones'>
<p></p>
</li>
</ul>
</body>
</html>
এবং নিয়ামকের জন্য জাভাস্ক্রিপ্ট:
var phonecatApp = angular.module('phonecatApp', []);
phonecatApp.controller('PhoneListCtrl', function($scope) {
$scope.phones = [
{'name': 'Nexus S',
'snippet': 'Fast just got faster with Nexus S.'},
{'name': 'Motorola XOOM with Wi-Fi',
'snippet': 'The Next, Next Generation tablet.'},
{'name': 'MOTOROLA XOOM',
'snippet': 'The Next, Next Generation tablet.'}
];
});
যে কোনো সময় অন্তর্নিহিত মডেল ডেটা পরিবর্তিত হয়, DOM-এ আমাদের তালিকা আপডেট করা হয়। কৌণিক কিভাবে এটি অর্জন করে? আচ্ছা, পর্দার আড়ালে এটা নোংরা-চেকিং নামে কিছু করছে।
নোংরা-চেকিংয়ের মূল ধারণাটি হল যে কোনও সময় ডেটা পরিবর্তিত হতে পারে, লাইব্রেরিতে যেতে হবে এবং এটি একটি ডাইজেস্ট বা পরিবর্তন চক্রের মাধ্যমে পরিবর্তন হয়েছে কিনা তা পরীক্ষা করতে হবে। Angular এর ক্ষেত্রে, একটি ডাইজেস্ট চক্র কোনো পরিবর্তন হয়েছে কিনা তা দেখার জন্য নিবন্ধিত সমস্ত অভিব্যক্তি চিহ্নিত করে। এটি একটি মডেলের পূর্ববর্তী মান সম্পর্কে জানে এবং যদি সেগুলি পরিবর্তিত হয় তবে একটি পরিবর্তন ইভেন্ট বরখাস্ত করা হয়৷ একজন ডেভেলপারের জন্য, এখানে প্রধান সুবিধা হল আপনি কাঁচা জাভাস্ক্রিপ্ট অবজেক্ট ডেটা ব্যবহার করতে পারবেন যা ব্যবহারে আনন্দদায়ক এবং মোটামুটি ভালভাবে রচনা করে। নেতিবাচক দিক হল এটির খারাপ অ্যালগরিদমিক আচরণ রয়েছে এবং এটি সম্ভাব্য খুব ব্যয়বহুল।
এই অপারেশনের খরচ পর্যবেক্ষিত বস্তুর মোট সংখ্যার সমানুপাতিক। আমাকে অনেক নোংরা চেকিং করতে হতে পারে। ডাটা পরিবর্তিত হলে নোংরা-চেকিং ট্রিগার করার একটি উপায়ের প্রয়োজন হতে পারে। এর জন্য অনেক চতুর কৌশল ফ্রেমওয়ার্ক ব্যবহার করা হয়। এটি কখনই নিখুঁত হতে চলেছে কিনা তা স্পষ্ট নয়।
ওয়েব ইকোসিস্টেমের নিজস্ব ঘোষণামূলক প্রক্রিয়া উদ্ভাবন এবং বিকশিত করার আরও ক্ষমতা থাকা উচিত, যেমন
- সীমাবদ্ধতা-ভিত্তিক মডেল সিস্টেম
- স্বয়ংক্রিয়-স্থিরতা সিস্টেম (যেমন ইনডেক্সডডিবি বা স্থানীয় স্টোরেজের স্থায়ী পরিবর্তন)
- ধারক বস্তু (আঙ্গুর, মেরুদণ্ড)
কনটেইনার অবজেক্ট হল যেখানে একটি ফ্রেমওয়ার্ক এমন বস্তু তৈরি করে যা ভিতরে ডেটা ধরে রাখে। তাদের কাছে ডেটা অ্যাক্সেসার রয়েছে এবং আপনি যা সেট করেন বা পান তা তারা ক্যাপচার করতে পারে এবং অভ্যন্তরীণভাবে সম্প্রচার করতে পারে। এই ভাল কাজ করে. এটি তুলনামূলকভাবে কার্যকরী এবং ভাল অ্যালগরিদমিক আচরণ রয়েছে। Ember ব্যবহার করে ধারক বস্তুর একটি উদাহরণ নীচে পাওয়া যাবে:
// Container objects
MyApp.president = Ember.Object.create({
name: "Barack Obama"
});
MyApp.country = Ember.Object.create({
// ending a property with "Binding" tells Ember to
// create a binding to the presidentName property
presidentNameBinding: "MyApp.president.name"
});
// Later, after Ember has resolved bindings
MyApp.country.get("presidentName");
// "Barack Obama"
// Data from the server needs to be converted
// Composes poorly with existing code
এখানে কী পরিবর্তিত হয়েছে তা আবিষ্কার করার ব্যয় পরিবর্তন হওয়া জিনিসের সংখ্যার সমানুপাতিক। আরেকটি সমস্যা হল এখন আপনি এই ভিন্ন ধরনের বস্তু ব্যবহার করছেন। সাধারণভাবে বলতে গেলে আপনি সার্ভার থেকে যে ডেটা পাচ্ছেন তা থেকে এই বস্তুগুলিতে রূপান্তর করতে হবে যাতে সেগুলি পর্যবেক্ষণযোগ্য হয়।
এটি বিদ্যমান জেএস কোডের সাথে বিশেষভাবে ভালভাবে রচনা করে না কারণ বেশিরভাগ কোড অনুমান করে যে এটি কাঁচা ডেটাতে কাজ করতে পারে। এই বিশেষ ধরনের বস্তুর জন্য নয়।
Introducing Object.observe()
আদর্শভাবে আমরা যা চাই তা হল উভয় জগতের সেরা - কাঁচা ডেটা অবজেক্টের (নিয়মিত জাভাস্ক্রিপ্ট অবজেক্ট) সমর্থন সহ ডেটা পর্যবেক্ষণ করার একটি উপায় যদি আমরা সব সময় সবকিছু নোংরা-চেক করার প্রয়োজন ছাড়াই AND বেছে নিই। ভালো অ্যালগরিদমিক আচরণ সহ কিছু। এমন কিছু যা ভালোভাবে রচনা করে এবং প্ল্যাটফর্মে বেক করা হয়। Object.observe()
টেবিলে যা নিয়ে আসে তারই সৌন্দর্য।
এটি আমাদের একটি বস্তু পর্যবেক্ষণ করতে, বৈশিষ্ট্যগুলিকে পরিবর্তন করতে এবং কী পরিবর্তন হয়েছে তার পরিবর্তন প্রতিবেদন দেখতে দেয়। কিন্তু তত্ত্ব সম্পর্কে যথেষ্ট, আসুন কিছু কোড তাকান!
Object.observe() এবং Object.unobserve()
আসুন কল্পনা করি যে আমাদের কাছে একটি সাধারণ ভ্যানিলা জাভাস্ক্রিপ্ট অবজেক্ট রয়েছে যা একটি মডেলের প্রতিনিধিত্ব করে:
// A model can be a simple vanilla object
var todoModel = {
label: 'Default',
completed: false
};
যখনই বস্তুতে মিউটেশন (পরিবর্তন) করা হয় তখন আমরা একটি কলব্যাক নির্দিষ্ট করতে পারি:
function observer(changes){
changes.forEach(function(change, i){
console.log('what property changed? ' + change.name);
console.log('how did it change? ' + change.type);
console.log('whats the current value? ' + change.object[change.name]);
console.log(change); // all changes
});
}
তারপরে আমরা Oo() ব্যবহার করে এই পরিবর্তনগুলি পর্যবেক্ষণ করতে পারি, আমাদের প্রথম আর্গুমেন্ট হিসাবে অবজেক্টে পাস করা এবং দ্বিতীয় হিসাবে কলব্যাক:
Object.observe(todoModel, observer);
আসুন আমাদের Todos মডেল অবজেক্টে কিছু পরিবর্তন করা শুরু করি:
todoModel.label = 'Buy some more milk';
কনসোল এ খুঁজছেন, আমরা কিছু দরকারী তথ্য ফিরে পেতে! আমরা জানি কি সম্পত্তি পরিবর্তিত হয়েছে, এটি কিভাবে পরিবর্তিত হয়েছে এবং নতুন মান কি।
উঃ! বিদায়, ডার্টি-চেকিং! আপনার সমাধির পাথরটি কমিক সানসে খোদাই করা উচিত। এর অন্য সম্পত্তি পরিবর্তন করা যাক. এইবার completeBy
:
todoModel.completeBy = '01/01/2014';
আমরা দেখতে পাচ্ছি আমরা আবার সফলভাবে একটি পরিবর্তন প্রতিবেদন ফিরে পেয়েছি:
দারুণ। যদি আমরা এখন আমাদের অবজেক্ট থেকে 'সম্পূর্ণ' সম্পত্তি মুছে ফেলার সিদ্ধান্ত নিই:
delete todoModel.completed;
আমরা দেখতে পাচ্ছি, প্রত্যাবর্তিত পরিবর্তনের প্রতিবেদনে মুছে ফেলার তথ্য অন্তর্ভুক্ত রয়েছে। প্রত্যাশিত হিসাবে, সম্পত্তির নতুন মান এখন অনির্ধারিত। সুতরাং, আমরা এখন জানি যে আপনি কখন বৈশিষ্ট্যগুলি যোগ করা হয়েছে তা জানতে পারবেন। যখন তারা মুছে ফেলা হয়েছে. মূলত, একটি বস্তুর বৈশিষ্ট্যের সেট ("নতুন", "মুছে ফেলা", "পুনরায় কনফিগার করা") এবং এটির প্রোটোটাইপ পরিবর্তন ( proto )।
যেকোনো পর্যবেক্ষণ ব্যবস্থার মতো, পরিবর্তনের জন্য শোনা বন্ধ করার জন্য একটি পদ্ধতিও বিদ্যমান। এই ক্ষেত্রে, এটি হল Object.unobserve()
, যা Oo() এর মতো একই স্বাক্ষর রয়েছে তবে এটিকে নিম্নরূপ বলা যেতে পারে:
Object.unobserve(todoModel, observer);
আমরা নীচে দেখতে পাচ্ছি, এটি চালানোর পরে অবজেক্টে করা যেকোন মিউটেশনের ফলে আর পরিবর্তন রেকর্ডের একটি তালিকা ফিরে আসে না।
আগ্রহের পরিবর্তনগুলি উল্লেখ করা
তাই আমরা একটি পর্যবেক্ষণ করা বস্তুর পরিবর্তনের তালিকা কিভাবে ফিরে পেতে হয় তার পেছনের মূল বিষয়গুলো দেখেছি। আপনি যদি সমস্ত পরিবর্তনের পরিবর্তে একটি বস্তুতে করা পরিবর্তনগুলির একটি উপসেটে আগ্রহী হন তবে কী হবে? প্রত্যেকেরই একটি স্প্যাম ফিল্টার প্রয়োজন। ঠিক আছে, পর্যবেক্ষকরা শুধুমাত্র সেই ধরনের পরিবর্তনগুলি নির্দিষ্ট করতে পারেন যা তারা একটি গ্রহণ তালিকার মাধ্যমে শুনতে চায়। এটি Oo() এর তৃতীয় আর্গুমেন্ট ব্যবহার করে উল্লেখ করা যেতে পারে:
Object.observe(obj, callback, optAcceptList)
আসুন এটি কীভাবে ব্যবহার করা যেতে পারে তার একটি উদাহরণ দিয়ে হাঁটুন:
// Like earlier, a model can be a simple vanilla object
var todoModel = {
label: 'Default',
completed: false
};
// We then specify a callback for whenever mutations
// are made to the object
function observer(changes){
changes.forEach(function(change, i){
console.log(change);
})
};
// Which we then observe, specifying an array of change
// types we're interested in
Object.observe(todoModel, observer, ['delete']);
// without this third option, the change types provided
// default to intrinsic types
todoModel.label = 'Buy some milk';
// note that no changes were reported
যদিও আমরা এখন লেবেল মুছে ফেলি, লক্ষ্য করুন যে এই ধরনের পরিবর্তন রিপোর্ট করা হয়েছে:
delete todoModel.label;
আপনি যদি Oo() তে গ্রহণযোগ্য প্রকারের একটি তালিকা নির্দিষ্ট না করেন তবে এটি "অভ্যন্তরীণ" অবজেক্ট পরিবর্তনের ধরনগুলিতে ডিফল্ট হয় ( add
, update
, delete
, reconfigure
, preventExtensions
(যখন একটি বস্তু অ-প্রসারণযোগ্য হয়ে উঠছে তা পর্যবেক্ষণযোগ্য নয়) )
বিজ্ঞপ্তি
Oo() এছাড়াও বিজ্ঞপ্তির ধারণার সাথে আসে। এগুলি আপনি ফোনে পাওয়া বিরক্তিকর জিনিসগুলির মতো কিছুই নয়, বরং দরকারী। বিজ্ঞপ্তিগুলি মিউটেশন পর্যবেক্ষকদের অনুরূপ। এগুলি মাইক্রো-টাস্কের শেষে ঘটে। ব্রাউজার প্রসঙ্গে, এটি প্রায় সবসময় বর্তমান ইভেন্ট হ্যান্ডলারের শেষে হতে চলেছে।
সময়টি চমৎকার কারণ সাধারণত একটি ইউনিট কাজ শেষ হয় এবং এখন পর্যবেক্ষকরা তাদের কাজ করতে পারেন। এটি একটি সুন্দর টার্ন-ভিত্তিক প্রক্রিয়াকরণ মডেল।
একটি নোটিফায়ার ব্যবহার করার জন্য ওয়ার্কফ্লো একটু এই মত দেখায়:
কোন বস্তুর বৈশিষ্ট্যগুলি পাওয়া বা সেট করার জন্য কাস্টম বিজ্ঞপ্তিগুলিকে সংজ্ঞায়িত করতে কীভাবে নোটিফায়ারগুলি ব্যবহার করা যেতে পারে তার একটি উদাহরণ দেখা যাক৷ এখানে মন্তব্যে চোখ রাখুন:
// Define a simple model
var model = {
a: {}
};
// And a separate variable we'll be using for our model's
// getter in just a moment
var _b = 2;
// Define a new property 'b' under 'a' with a custom
// getter and setter
Object.defineProperty(model.a, 'b', {
get: function () {
return _b;
},
set: function (b) {
// Whenever 'b' is set on the model
// notify the world about a specific type
// of change being made. This gives you a huge
// amount of control over notifications
Object.getNotifier(this).notify({
type: 'update',
name: 'b',
oldValue: _b
});
// Let's also log out the value anytime it gets
// set for kicks
console.log('set', b);
_b = b;
}
});
// Set up our observer
function observer(changes) {
changes.forEach(function (change, i) {
console.log(change);
})
}
// Begin observing model.a for changes
Object.observe(model.a, observer);
এখানে আমরা রিপোর্ট করি যখন ডেটা বৈশিষ্ট্যের মান পরিবর্তন হয় ("আপডেট")। অবজেক্টের ইমপ্লিমেন্টেশন রিপোর্ট করতে বেছে নেয় অন্য কিছু ( notifier.notifyChange()
)।
ওয়েব প্ল্যাটফর্মে বছরের পর বছর অভিজ্ঞতা আমাদের শিখিয়েছে যে একটি সিঙ্ক্রোনাস পদ্ধতি হল প্রথম জিনিস যা আপনি চেষ্টা করেন কারণ এটি আপনার মাথার চারপাশে মোড়ানো সবচেয়ে সহজ। সমস্যা হল এটি একটি মৌলিকভাবে বিপজ্জনক প্রক্রিয়াকরণ মডেল তৈরি করে। আপনি যদি কোড লিখছেন এবং বলছেন, একটি বস্তুর সম্পত্তি আপডেট করুন, আপনি সত্যিই এমন পরিস্থিতি চান না যে সেই বস্তুর সম্পত্তি আপডেট করার জন্য কিছু স্বেচ্ছাচারী কোডকে যা ইচ্ছা তা করার জন্য আমন্ত্রণ জানানো হতে পারে। আপনি একটি ফাংশন মাঝখানে মাধ্যমে চলমান হিসাবে আপনার অনুমান অবৈধ করা আদর্শ নয়.
আপনি যদি একজন পর্যবেক্ষক হন, কেউ যদি কিছুর মাঝখানে থাকে তবে আপনি আদর্শভাবে ডাকতে চান না। আপনি বিশ্বের একটি অসংলগ্ন অবস্থায় কাজ করতে যেতে বলা হবে না চান. অনেক বেশি ত্রুটি পরীক্ষা করে শেষ করুন। অনেক বেশি খারাপ পরিস্থিতি সহ্য করার চেষ্টা করা এবং সাধারণত, এটি কাজ করার জন্য একটি কঠিন মডেল। Async মোকাবেলা করা কঠিন কিন্তু দিনের শেষে এটি একটি ভাল মডেল।
এই সমস্যার সমাধান হল সিন্থেটিক পরিবর্তন রেকর্ড।
সিন্থেটিক পরিবর্তন রেকর্ড
মূলত, আপনি যদি অ্যাক্সেসর বা কম্পিউটেড প্রপার্টি পেতে চান তাহলে এই মানগুলি পরিবর্তন হলে তা জানানো আপনার দায়িত্ব। এটি একটি সামান্য অতিরিক্ত কাজ কিন্তু এটি এই প্রক্রিয়াটির প্রথম-শ্রেণীর বৈশিষ্ট্য হিসাবে ডিজাইন করা হয়েছে এবং এই বিজ্ঞপ্তিগুলি অন্তর্নিহিত ডেটা অবজেক্ট থেকে বাকি বিজ্ঞপ্তিগুলির সাথে বিতরণ করা হবে। তথ্য বৈশিষ্ট্য থেকে.
পর্যবেক্ষণকারী অ্যাক্সেসর এবং গণনা করা বৈশিষ্ট্যগুলি নোটিফাইয়ের মাধ্যমে সমাধান করা যেতে পারে - Oo() এর আরেকটি অংশ। বেশীরভাগ পর্যবেক্ষণ সিস্টেম প্রাপ্ত মান পর্যবেক্ষণের কিছু রূপ চায়। এটা করার অনেক উপায় আছে। Oo "সঠিক" উপায় হিসাবে কোন রায় দেয় না। গণনা করা বৈশিষ্ট্যগুলি অ্যাক্সেসর হওয়া উচিত যা অভ্যন্তরীণ (ব্যক্তিগত) অবস্থার পরিবর্তন হলে বিজ্ঞপ্তি দেয় ।
আবার, ওয়েবডেভের আশা করা উচিত লাইব্রেরিগুলিকে নোটিফাই করা এবং গণনা করা বৈশিষ্ট্যগুলির বিভিন্ন পদ্ধতির সহজ (এবং বয়লারপ্লেট কমাতে) সাহায্য করবে।
এর পরবর্তী উদাহরণ সেট আপ করা যাক, যা একটি বৃত্ত ক্লাস। এখানে ধারণা হল যে আমাদের এই বৃত্ত আছে এবং একটি ব্যাসার্ধ সম্পত্তি আছে। এই ক্ষেত্রে ব্যাসার্ধ একটি অ্যাক্সেসর এবং যখন এর মান পরিবর্তন হয় তখন এটি আসলে নিজের জন্য অবহিত করবে যে মান পরিবর্তিত হয়েছে। এই অবজেক্ট বা অন্য যেকোন অবজেক্টে অন্য সব পরিবর্তনের সাথে এটি বিতরণ করা হবে। মূলত, আপনি যদি এমন একটি বস্তু বাস্তবায়ন করছেন যা আপনি সিন্থেটিক বা গণনাকৃত বৈশিষ্ট্য পেতে চান বা এটি কীভাবে কাজ করবে তার জন্য আপনাকে একটি কৌশল বেছে নিতে হবে। একবার আপনি, এটি সম্পূর্ণরূপে আপনার সিস্টেমে মাপসই করা হবে.
DevTools-এ এটি কাজ করে দেখতে কোডটি এড়িয়ে যান।
function Circle(r) {
var radius = r;
var notifier = Object.getNotifier(this);
function notifyAreaAndRadius(radius) {
notifier.notify({
type: 'update',
name: 'radius',
oldValue: radius
})
notifier.notify({
type: 'update',
name: 'area',
oldValue: Math.pow(radius * Math.PI, 2)
});
}
Object.defineProperty(this, 'radius', {
get: function() {
return radius;
},
set: function(r) {
if (radius === r)
return;
notifyAreaAndRadius(radius);
radius = r;
}
});
Object.defineProperty(this, 'area', {
get: function() {
return Math.pow(radius, 2) * Math.PI;
},
set: function(a) {
r = Math.sqrt(a/Math.PI);
notifyAreaAndRadius(radius);
radius = r;
}
});
}
function observer(changes){
changes.forEach(function(change, i){
console.log(change);
})
}
অ্যাক্সেসর বৈশিষ্ট্য
অ্যাক্সেসর বৈশিষ্ট্যের উপর একটি দ্রুত নোট। আমরা আগে উল্লেখ করেছি যে ডেটা বৈশিষ্ট্যগুলির জন্য শুধুমাত্র মান পরিবর্তনগুলি পর্যবেক্ষণযোগ্য। গণনা করা বৈশিষ্ট্য বা অ্যাক্সেসরগুলির জন্য নয়। কারণ হল যে জাভাস্ক্রিপ্টে অ্যাক্সেসরগুলির মান পরিবর্তনের ধারণা নেই। একটি অ্যাক্সেসর শুধুমাত্র ফাংশন একটি সংগ্রহ.
আপনি যদি একটি অ্যাক্সেসরকে জাভাস্ক্রিপ্ট বরাদ্দ করেন তবে সেখানে ফাংশনটি চালু করে এবং এর দৃষ্টিকোণ থেকে কিছুই পরিবর্তন হয়নি। এটি শুধু কিছু কোড চালানোর সুযোগ দিয়েছে।
সমস্যাটি শব্দার্থগতভাবে আমরা আমাদের উপরের অ্যাসাইনমেন্টটি মান - 5 এর সাথে দেখতে পারি। আমরা এখানে কি ঘটেছে জানতে সক্ষম হওয়া উচিত. এটি আসলে একটি অমীমাংসিত সমস্যা। উদাহরণ দেখায় কেন. এর দ্বারা কী বোঝানো হয়েছে তা জানার কোনও সিস্টেমের পক্ষে সত্যিই কোনও উপায় নেই কারণ এটি নির্বিচারে কোড হতে পারে। এই ক্ষেত্রে এটি যা ইচ্ছা তাই করতে পারে। এটি প্রতিবার অ্যাক্সেস করার সময় এটি মান আপডেট করে এবং তাই এটি পরিবর্তিত কিনা তা জিজ্ঞাসা করা খুব বেশি অর্থপূর্ণ নয়।
একটি কলব্যাক সহ একাধিক বস্তু পর্যবেক্ষণ করা
Oo() এর সাথে সম্ভব আরেকটি প্যাটার্ন হল একক কলব্যাক পর্যবেক্ষকের ধারণা। এটি একটি একক কলব্যাককে অনেকগুলি বিভিন্ন বস্তুর জন্য "পর্যবেক্ষক" হিসাবে ব্যবহার করার অনুমতি দেয়। কলব্যাকটি "মাইক্রোটাস্কের শেষে" (মিউটেশন পর্যবেক্ষকদের সাথে সাদৃশ্য লক্ষ্য করুন) লক্ষ্য করা সমস্ত বস্তুতে পরিবর্তনের সম্পূর্ণ সেট সরবরাহ করা হবে।
বড় মাপের পরিবর্তন
হতে পারে আপনি একটি reaaaally বড় অ্যাপে কাজ করছেন এবং নিয়মিত বড় আকারের পরিবর্তনের সাথে কাজ করতে হবে। অবজেক্টগুলি বৃহত্তর শব্দার্থিক পরিবর্তনগুলি বর্ণনা করতে ইচ্ছুক হতে পারে যা অনেকগুলি বৈশিষ্ট্যকে আরও কমপ্যাক্ট উপায়ে প্রভাবিত করবে (টন সম্পত্তি পরিবর্তন সম্প্রচারের পরিবর্তে)।
Oo() দুটি নির্দিষ্ট ইউটিলিটি আকারে এটিতে সহায়তা করে: notifier.performChange()
এবং notifier.notify()
, যা আমরা ইতিমধ্যেই চালু করেছি।
আসুন এটিকে একটি উদাহরণে দেখি যে কীভাবে বড় আকারের পরিবর্তনগুলি বর্ণনা করা যেতে পারে যেখানে আমরা কিছু গণিত উপযোগিতা (গুণ, বৃদ্ধি, বৃদ্ধি এবং গুনগত) সহ একটি Thingy অবজেক্টকে সংজ্ঞায়িত করি। যে কোনো সময় একটি ইউটিলিটি ব্যবহার করা হয়, এটি সিস্টেমকে বলে যে কাজের একটি সংগ্রহ একটি নির্দিষ্ট ধরনের পরিবর্তন নিয়ে গঠিত।
যেমন: notifier.performChange('foo', performFooChangeFn);
function Thingy(a, b, c) {
this.a = a;
this.b = b;
}
Thingy.MULTIPLY = 'multiply';
Thingy.INCREMENT = 'increment';
Thingy.INCREMENT_AND_MULTIPLY = 'incrementAndMultiply';
Thingy.prototype = {
increment: function(amount) {
var notifier = Object.getNotifier(this);
// Tell the system that a collection of work comprises
// a given changeType. e.g
// notifier.performChange('foo', performFooChangeFn);
// notifier.notify('foo', 'fooChangeRecord');
notifier.performChange(Thingy.INCREMENT, function() {
this.a += amount;
this.b += amount;
}, this);
notifier.notify({
object: this,
type: Thingy.INCREMENT,
incremented: amount
});
},
multiply: function(amount) {
var notifier = Object.getNotifier(this);
notifier.performChange(Thingy.MULTIPLY, function() {
this.a *= amount;
this.b *= amount;
}, this);
notifier.notify({
object: this,
type: Thingy.MULTIPLY,
multiplied: amount
});
},
incrementAndMultiply: function(incAmount, multAmount) {
var notifier = Object.getNotifier(this);
notifier.performChange(Thingy.INCREMENT_AND_MULTIPLY, function() {
this.increment(incAmount);
this.multiply(multAmount);
}, this);
notifier.notify({
object: this,
type: Thingy.INCREMENT_AND_MULTIPLY,
incremented: incAmount,
multiplied: multAmount
});
}
}
তারপরে আমরা আমাদের অবজেক্টের জন্য দুটি পর্যবেক্ষককে সংজ্ঞায়িত করি: একটি যা পরিবর্তনের জন্য একটি ক্যাচ-অল এবং অন্যটি যা শুধুমাত্র আমাদের সংজ্ঞায়িত নির্দিষ্ট ধরনের গ্রহণের বিষয়ে রিপোর্ট করবে (Thingy.INCREMENT, Thingy.MULTIPLY, Thingy.INCREMENT_AND_MULTIPLY)।
var observer, observer2 = {
records: undefined,
callbackCount: 0,
reset: function() {
this.records = undefined;
this.callbackCount = 0;
},
};
observer.callback = function(r) {
console.log(r);
observer.records = r;
observer.callbackCount++;
};
observer2.callback = function(r){
console.log('Observer 2', r);
}
Thingy.observe = function(thingy, callback) {
// Object.observe(obj, callback, optAcceptList)
Object.observe(thingy, callback, [Thingy.INCREMENT,
Thingy.MULTIPLY,
Thingy.INCREMENT_AND_MULTIPLY,
'update']);
}
Thingy.unobserve = function(thingy, callback) {
Object.unobserve(thingy);
}
আমরা এখন এই কোড দিয়ে খেলা শুরু করতে পারি। আসুন একটি নতুন জিনিস সংজ্ঞায়িত করা যাক:
var thingy = new Thingy(2, 4);
এটি পর্যবেক্ষণ করুন এবং তারপর কিছু পরিবর্তন করুন। ওএমজি, এত মজা। অনেক জিনিস!
// Observe thingy
Object.observe(thingy, observer.callback);
Thingy.observe(thingy, observer2.callback);
// Play with the methods thingy exposes
thingy.increment(3); // { a: 5, b: 7 }
thingy.b++; // { a: 5, b: 8 }
thingy.multiply(2); // { a: 10, b: 16 }
thingy.a++; // { a: 11, b: 16 }
thingy.incrementAndMultiply(2, 2); // { a: 26, b: 36 }
"পারফর্ম ফাংশন" এর ভিতরের সবকিছুকে "বড়-পরিবর্তনের" কাজ বলে মনে করা হয়। যে সকল পর্যবেক্ষক "বিগ-পরিবর্তন" গ্রহণ করেন তারা শুধুমাত্র "বড়-পরিবর্তন" রেকর্ড পাবেন। যে সকল পর্যবেক্ষকরা "ফাংশন সম্পাদন" করে সেই কাজের ফলে অন্তর্নিহিত পরিবর্তনগুলি পাবেন না।
অ্যারে পর্যবেক্ষণ করা হচ্ছে
আমরা কিছু সময়ের জন্য বস্তুর পরিবর্তন পর্যবেক্ষণ সম্পর্কে কথা বলেছি কিন্তু অ্যারে সম্পর্কে কি?! মহান প্রশ্ন. যখন কেউ আমাকে বলে, "দারুণ প্রশ্ন।" আমি কখনই তাদের উত্তর শুনি না কারণ আমি এমন একটি দুর্দান্ত প্রশ্ন জিজ্ঞাসা করার জন্য নিজেকে অভিনন্দন জানাতে ব্যস্ত, কিন্তু আমি বিভ্রান্ত হই। অ্যারেগুলির সাথে কাজ করার জন্য আমাদের কাছে নতুন পদ্ধতি রয়েছে!
Array.observe()
এমন একটি পদ্ধতি যা বড় আকারের পরিবর্তনগুলিকে নিজের মধ্যে বিবেচনা করে - উদাহরণস্বরূপ - স্প্লাইস, আনশিফ্ট বা এমন কিছু যা স্পষ্টভাবে এটির দৈর্ঘ্য পরিবর্তন করে - একটি "স্প্লিস" পরিবর্তন রেকর্ড হিসাবে। অভ্যন্তরীণভাবে এটি notifier.performChange("splice",...)
ব্যবহার করে।
এখানে একটি উদাহরণ যেখানে আমরা একটি মডেল "অ্যারে" পর্যবেক্ষণ করি এবং একইভাবে অন্তর্নিহিত ডেটাতে কোনো পরিবর্তন হলে পরিবর্তনের একটি তালিকা ফিরে পাই:
var model = ['Buy some milk', 'Learn to code', 'Wear some plaid'];
var count = 0;
Array.observe(model, function(changeRecords) {
count++;
console.log('Array observe', changeRecords, count);
});
model[0] = 'Teach Paul Lewis to code';
model[1] = 'Channel your inner Paul Irish';
কর্মক্ষমতা
Oo() এর কম্পিউটেশনাল পারফরম্যান্সের প্রভাব সম্পর্কে চিন্তা করার উপায় হল এটি একটি রিড ক্যাশের মতো চিন্তা করা। সাধারণভাবে বলতে গেলে, একটি ক্যাশে একটি দুর্দান্ত পছন্দ যখন (গুরুত্ব অনুসারে):
- পড়ার ফ্রিকোয়েন্সি লেখার ফ্রিকোয়েন্সি প্রাধান্য দেয়।
- আপনি একটি ক্যাশে তৈরি করতে সক্ষম হন যা পড়ার সময় অ্যালগরিদমিকভাবে আরও ভাল পারফরম্যান্সের জন্য লেখার সময় জড়িত ক্রমাগত পরিমাণে কাজ করে।
- লেখার ক্রমাগত ধীরগতি গ্রহণযোগ্য।
Oo() 1 এর মতো ব্যবহারের ক্ষেত্রে ডিজাইন করা হয়েছে)।
ডার্টি-চেকিংয়ের জন্য আপনি যে সমস্ত ডেটা পর্যবেক্ষণ করছেন তার একটি কপি রাখা প্রয়োজন। এর মানে হল আপনি নোংরা-চেক করার জন্য একটি স্ট্রাকচারাল মেমরি খরচ বহন করেন যা আপনি Oo() দিয়ে পাবেন না। ডার্টি-চেকিং, যদিও একটি শালীন স্টপ-গ্যাপ সমাধান, এটি একটি মৌলিকভাবে ফাঁস হওয়া বিমূর্ততা যা অ্যাপ্লিকেশনগুলির জন্য অপ্রয়োজনীয় জটিলতা তৈরি করতে পারে।
কেন? ওয়েল, ডার্টি-চেকিং যে কোনো সময় ডাটা পরিবর্তন হতে পারে চালাতে হবে। এটি করার জন্য সহজভাবে একটি খুব শক্তিশালী উপায় নেই এবং এটির যেকোন পদ্ধতির উল্লেখযোগ্য নেতিবাচক দিক রয়েছে (যেমন ভোটের ব্যবধানে পরীক্ষা করা দৃশ্যমান আর্টিফ্যাক্ট এবং কোড উদ্বেগের মধ্যে রেসের অবস্থার ঝুঁকি তৈরি করে)। নোংরা-পরীক্ষার জন্য পর্যবেক্ষকদের একটি বিশ্বব্যাপী রেজিস্ট্রিও প্রয়োজন, মেমরি-লিকের ঝুঁকি তৈরি করে এবং Oo() খরচ এড়িয়ে যায়।
আসুন কিছু সংখ্যা দেখে নেওয়া যাক।
নীচের বেঞ্চমার্ক পরীক্ষাগুলি ( GitHub- এ উপলব্ধ) আমাদেরকে নোংরা-চেকিং বনাম Oo() তুলনা করার অনুমতি দেয়। এগুলি অবজার্ভড-অবজেক্ট-সেট-সাইজ বনাম সংখ্যা-অফ-মিউটেশনের গ্রাফ হিসাবে গঠন করা হয়েছে। সাধারণ ফলাফল হল যে নোংরা-চেকিং কর্মক্ষমতা অ্যালগরিদমিকভাবে পর্যবেক্ষিত বস্তুর সংখ্যার সমানুপাতিক যেখানে Oo() কর্মক্ষমতা তৈরি করা মিউটেশনের সংখ্যার সমানুপাতিক।
ডার্টি-চেকিং
Object.observe() সহ ক্রোম চালু হয়েছে
Polyfilling Object.observe()
দুর্দান্ত - তাই Oo() Chrome 36 এ ব্যবহার করা যেতে পারে, কিন্তু অন্যান্য ব্রাউজারে এটি ব্যবহার করার বিষয়ে কী? আমরা আপনাকে কভার করেছি. Polymer's Observe-JS হল Oo() এর জন্য একটি পলিফিল যা উপস্থিত থাকলে নেটিভ ইমপ্লিমেন্টেশন ব্যবহার করবে, কিন্তু অন্যথায় এটিকে পলিফিল করে এবং উপরে কিছু দরকারী সুগারিং অন্তর্ভুক্ত করে। এটি বিশ্বের একটি সামগ্রিক দৃষ্টিভঙ্গি অফার করে যা পরিবর্তনগুলিকে সংক্ষিপ্ত করে এবং কী পরিবর্তিত হয়েছে তার একটি প্রতিবেদন সরবরাহ করে৷ দুটি সত্যিই শক্তিশালী জিনিস এটি প্রকাশ করে:
- আপনি পাথ পর্যবেক্ষণ করতে পারেন. এর মানে আপনি বলতে পারেন, আমি একটি প্রদত্ত বস্তু থেকে "foo.bar.baz" পর্যবেক্ষণ করতে চাই এবং সেই পথে মান পরিবর্তন হলে তারা আপনাকে বলবে। যদি পথটি পৌঁছানো যায় না, তবে এটি মানটিকে অনির্ধারিত বলে বিবেচনা করে।
একটি প্রদত্ত বস্তু থেকে একটি পথে একটি মান পর্যবেক্ষণের উদাহরণ:
var obj = { foo: { bar: 'baz' } };
var observer = new PathObserver(obj, 'foo.bar');
observer.open(function(newValue, oldValue) {
// respond to obj.foo.bar having changed value.
});
- এটি আপনাকে অ্যারে স্প্লাইস সম্পর্কে বলবে। অ্যারে স্প্লাইসগুলি মূলত স্প্লাইস অপারেশনগুলির ন্যূনতম সেট যা আপনাকে অ্যারের পুরানো সংস্করণটিকে অ্যারের নতুন সংস্করণে রূপান্তর করতে একটি অ্যারেতে সম্পাদন করতে হবে। এটি এক ধরনের রূপান্তর বা অ্যারের ভিন্ন দৃশ্য। পুরানো অবস্থা থেকে নতুন রাজ্যে যাওয়ার জন্য আপনাকে ন্যূনতম পরিমাণ কাজ করতে হবে।
স্প্লাইসের ন্যূনতম সেট হিসাবে একটি অ্যারেতে পরিবর্তনগুলি রিপোর্ট করার উদাহরণ:
var arr = [0, 1, 2, 4];
var observer = new ArrayObserver(arr);
observer.open(function(splices) {
// respond to changes to the elements of arr.
splices.forEach(function(splice) {
splice.index; // index position that the change occurred.
splice.removed; // an array of values representing the sequence of elements which were removed
splice.addedCount; // the number of elements which were inserted.
});
});
ফ্রেমওয়ার্ক এবং Object.observe()
উল্লিখিত হিসাবে, Oo() ফ্রেমওয়ার্ক এবং লাইব্রেরিগুলিকে তাদের ডেটা-বাইন্ডিংয়ের কার্যকারিতা উন্নত করার একটি বিশাল সুযোগ দেবে ব্রাউজারে যা বৈশিষ্ট্য সমর্থন করে।
Ember থেকে Yehuda Katz এবং Erik Bryn নিশ্চিত করেছেন যে Oo() এর জন্য সমর্থন যোগ করা Ember-এর নিকট-মেয়াদী রোডম্যাপে রয়েছে। Angular এর Misko Hervy Angular 2.0 এর উন্নত পরিবর্তন সনাক্তকরণের উপর একটি ডিজাইন ডক লিখেছেন। তাদের দীর্ঘমেয়াদী পন্থা হবে Object.observe() এর সুবিধা নেওয়া যখন এটি Chrome স্থিতিশীল অবস্থায় অবতরণ করে, Watchtower.js বেছে নেয়, ততক্ষণ পর্যন্ত তাদের নিজস্ব পরিবর্তন সনাক্তকরণ পদ্ধতি। সুউউপার উত্তেজনাপূর্ণ।
উপসংহার
Oo() ওয়েব প্ল্যাটফর্মের একটি শক্তিশালী সংযোজন যা আপনি আজই ব্যবহার করতে পারেন।
আমরা আশাবাদী যে সময়ের সাথে সাথে বৈশিষ্ট্যটি আরও ব্রাউজারে অবতরণ করবে, যা জাভাস্ক্রিপ্ট ফ্রেমওয়ার্কগুলিকে নেটিভ অবজেক্ট পর্যবেক্ষণ ক্ষমতাগুলিতে অ্যাক্সেস থেকে পারফরম্যান্স বুস্ট করার অনুমতি দেবে। যারা ক্রোমকে লক্ষ্য করে তাদের ক্রোম 36 (এবং তার উপরে) ওও() ব্যবহার করতে সক্ষম হওয়া উচিত এবং বৈশিষ্ট্যটি ভবিষ্যতের অপেরা রিলিজেও উপলব্ধ হওয়া উচিত।
সুতরাং, এগিয়ে যান এবং Object.observe()
সম্পর্কে জাভাস্ক্রিপ্ট ফ্রেমওয়ার্কের লেখকদের সাথে কথা বলুন এবং কীভাবে তারা আপনার অ্যাপে ডেটা-বাইন্ডিংয়ের কার্যকারিতা উন্নত করতে এটি ব্যবহার করার পরিকল্পনা করছেন। সামনে অবশ্যই সবচেয়ে উত্তেজনাপূর্ণ সময় আছে!
সম্পদ
- Object.observe() হারমনি উইকিতে >
- রিক ওয়াল্ড্রন দ্বারা Object.observe() এর সাথে ডেটাবাইন্ডিং
- আপনি Object.observe() - JSConf সম্পর্কে যা কিছু জানতে চেয়েছিলেন
- কেন Object.observe() সেরা ES7 বৈশিষ্ট্য
Rafael Weinstein, Jake Archibald, Eric Bidelman, Paul Kinlan এবং Vivian Cromwell কে তাদের ইনপুট এবং পর্যালোচনার জন্য ধন্যবাদ।