AngularJS: কোনও পরিষেবার বৈশিষ্ট্যের সাথে বাধ্যবাধকতার সঠিক উপায়


162

অ্যাঙ্গুলারজেএস-এ কোনও পরিষেবার সম্পত্তিতে কীভাবে বাঁধতে হয় তার সেরা অনুশীলনের সন্ধান করছি।

অ্যাঙ্গুলারজেএস ব্যবহার করে তৈরি করা পরিষেবার মধ্যে কীভাবে বৈশিষ্ট্যগুলিতে আবদ্ধ থাকা যায় তা বুঝতে আমি একাধিক উদাহরণের মাধ্যমে কাজ করেছি।

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

কোনও পরিষেবাতে সম্পত্তি বাঁধার সময় এই উদাহরণগুলির মধ্যে দুটিকেই কী পছন্দ করা হয় বা অন্য কোনও বিকল্প রয়েছে যা সম্পর্কে আমি সচেতন নই বা প্রস্তাবিত হবে?

এই উদাহরণগুলির ভিত্তিটি হ'ল পরিষেবাটি প্রতি 5 সেকেন্ডে তার "বৈশিষ্ট্যগুলি সর্বশেষ আপডেট" এবং "কল" আপডেট করে। একবার পরিষেবা বৈশিষ্ট্য আপডেট হয়ে গেলে ভিউতে এই পরিবর্তনগুলি প্রতিফলিত করা উচিত। এই দুটি উদাহরণই সফলভাবে কাজ করে; আমি আরও অবাক হই যে এটি করার আরও ভাল উপায় আছে কিনা।

বেসিক বাঁধাই

নিম্নলিখিত কোডটি এখানে দেখতে এবং চালানো যেতে পারে: http://plnkr.co/edit/d3c16z

<html>
<body ng-app="ServiceNotification" >

    <div ng-controller="TimerCtrl1" style="border-style:dotted"> 
        TimerCtrl1 <br/>
        Last Updated: {{timerData.lastUpdated}}<br/>
        Last Updated: {{timerData.calls}}<br/>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
    <script type="text/javascript">
        var app = angular.module("ServiceNotification", []);

        function TimerCtrl1($scope, Timer) {
            $scope.timerData = Timer.data;
        };

        app.factory("Timer", function ($timeout) {
            var data = { lastUpdated: new Date(), calls: 0 };

            var updateTimer = function () {
                data.lastUpdated = new Date();
                data.calls += 1;
                console.log("updateTimer: " + data.lastUpdated);

                $timeout(updateTimer, 5000);
            };
            updateTimer();

            return {
                data: data
            };
        });
    </script>
</body>
</html>

আমি অন্য যেভাবে পরিষেবা বৈশিষ্ট্যের সাথে বাধ্যতামূলক সমাধান করেছি তা হ'ল $ সুযোগ। নিয়ামকটি দেখুন।

$ সুযোগ। $ ঘড়ি

নিম্নলিখিত কোডটি এখানে দেখতে এবং চালানো যেতে পারে: http://plnkr.co/edit/dSBlC9

<html>
<body ng-app="ServiceNotification">
    <div style="border-style:dotted" ng-controller="TimerCtrl1">
        TimerCtrl1<br/>
        Last Updated: {{lastUpdated}}<br/>
        Last Updated: {{calls}}<br/>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
    <script type="text/javascript">
        var app = angular.module("ServiceNotification", []);

        function TimerCtrl1($scope, Timer) {
            $scope.$watch(function () { return Timer.data.lastUpdated; },
                function (value) {
                    console.log("In $watch - lastUpdated:" + value);
                    $scope.lastUpdated = value;
                }
            );

            $scope.$watch(function () { return Timer.data.calls; },
                function (value) {
                    console.log("In $watch - calls:" + value);
                    $scope.calls = value;
                }
            );
        };

        app.factory("Timer", function ($timeout) {
            var data = { lastUpdated: new Date(), calls: 0 };

            var updateTimer = function () {
                data.lastUpdated = new Date();
                data.calls += 1;
                console.log("updateTimer: " + data.lastUpdated);

                $timeout(updateTimer, 5000);
            };
            updateTimer();

            return {
                data: data
            };
        });
    </script>
</body>
</html>

আমি সচেতন যে আমি $ রুটস্কোপ। The পরিষেবাতে সম্প্রচার করতে এবং নিয়ামকটিতে $ মূল $ ব্যবহার করতে পারি, তবে অন্য যে উদাহরণগুলিতে আমি প্রথম সম্প্রচারে $ সম্প্রচার / use ব্যবহারটি তৈরি করেছি তা ক্যাপচার নয় নিয়ামক, তবে অতিরিক্ত সম্প্রচারিত কলগুলি নিয়ামকটিতে ট্রিগার করা হয়। আপনি যদি $ রুটস্কোপ $ সম্প্রচার সমস্যা সমাধানের কোনও উপায় সম্পর্কে অবগত হন তবে দয়া করে একটি উত্তর সরবরাহ করুন।

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


হালনাগাদ

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


আমি মনে করি জোশ ডেভিড মিলারের উত্তর গিল বীরমানের চেয়ে উত্তম। এবং $ ওয়াচ, $ ওয়াচগ্রুপ এবং $ ওয়াচ কালেকশন ব্যবহার এটিকে আরও উন্নত করতে পারে। মাঝারি থেকে বড় আকারের অ্যাপ্লিকেশনগুলিতে উদ্বেগগুলি পৃথক করা খুব গুরুত্বপূর্ণ।
জোনাথন

@ বারেদেভ আমি মনে করি উভয় উত্তর কার্যকর ছিল না এবং নতুন বিকাশকারীরা এগুলি সম্পূর্ণ ভুল বুঝতে পারবেন।
জালাবোজা

আপনার যে সমস্যাটি সম্পর্কে জিজ্ঞাসা করা হচ্ছে তা রেফারেন্সিং অবজেক্টগুলির স্থানীয় জাভাস্ক্রিপ্টের পরিবর্তনশীল আচরণ সম্পর্কিত, আমি নীচে কিছুটা ব্যাখ্যা যুক্ত করেছি
জালাবোজা

উত্তর:


100

দ্বিতীয় পদ্ধতির কিছু উপকারিতা এবং বিবেচনা বিবেচনা করুন :

  • 0 এর {{lastUpdated}} পরিবর্তে {{timerData.lastUpdated}}, যা কেবল সহজেই হতে পারে {{timer.lastUpdated}}, যা আমি তর্ক করতে পারি এটি আরও পাঠযোগ্য (তবে আসুন তর্ক করা উচিত না ... আমি এই বিষয়টিকে একটি নিরপেক্ষ রেটিং দিচ্ছি যাতে আপনি নিজেরাই সিদ্ধান্ত নেন)

  • +1 এটি সুবিধাজনক হতে পারে যে কন্ট্রোলার মার্কআপের জন্য এক ধরণের এপিআই হিসাবে কাজ করে যেমন কোনওভাবে যদি ডেটা মডেলের কাঠামো পরিবর্তন হয় তবে আপনি এইচটিএমএল আংশিক স্পর্শ না করেই নিয়ন্ত্রকের API ম্যাপিং আপডেট করতে পারবেন ।

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

  • -1 তদ্ব্যতীত, এই পদ্ধতির খুব DRY নয়।

  • -1 আপনি যদি ng-modelআপনার কোডের সাথে ডেটা বাঁধতে চান তবে আরও কম ডিআরওয়াই হয়ে উঠবে কারণ আপনাকে $scope.scalar_valuesএকটি নতুন আরএসটি কল করার জন্য নিয়ামকটিতে প্যাকেজটি পুনরায় প্যাকেজ করতে হবে।

  • -0.1 অতিরিক্ত পর্যবেক্ষক তৈরি করতে একটি ছোট্ট পারফরম্যান্স রয়েছে। এছাড়াও, যদি ডেটা বৈশিষ্ট্যগুলি কোনও মডেলটির সাথে সংযুক্ত থাকে যা কোনও নির্দিষ্ট নিয়ামক হিসাবে দেখার প্রয়োজন হয় না তবে তারা গভীর পর্যবেক্ষকদের জন্য অতিরিক্ত ওভারহেড তৈরি করবে।

  • -1 যদি একাধিক কন্ট্রোলার একই ডেটা মডেল প্রয়োজন? এর অর্থ হ'ল প্রতিটি মডেল পরিবর্তনের সাথে আপডেট করার জন্য আপনার একাধিক এপিআই রয়েছে।

$scope.timerData = Timer.data;এখনই শক্তিশালী লোভনীয় শব্দ শুরু হচ্ছে ... আসুন আমরা এই শেষ পয়েন্টটির আরও গভীর দিকে ঝাঁপ দাও ... আমরা কী ধরনের মডেল পরিবর্তনের কথা বলছিলাম? পিছনে একটি মডেল (সার্ভার)? বা এমন কোনও মডেল তৈরি করা হয়েছে যা কেবল সামনের দিকে থাকে? উভয় ক্ষেত্রেই, মূলত ডেটা ম্যাপিং এপিআই কী তা সামনের এন্ড সার্ভিস লেয়ার , (একটি কৌণিক কারখানা বা পরিষেবা) এর অন্তর্গত । (মনে রাখবেন যে আপনার প্রথম উদাহরণ - আমার পছন্দ - এর পরিষেবা স্তরে এমন কোনও এপিআই নেই , যা ভাল কারণ এটি যথেষ্ট সহজ কারণ এটির দরকার নেই))

উপসংহারে , সব কিছু decoupled করতে হবে না। এবং যতক্ষণ না ডেটা মডেল থেকে পুরোপুরি মার্কআপটিকে ডিক্লুপ করার ক্ষেত্রে ত্রুটিগুলি সুবিধাগুলি ছাড়িয়ে যায়।


কন্ট্রোলাররা সাধারণভাবে$scope = injectable.data.scalar এর সাথে জড়িত হওয়া উচিত নয় । বরং সঙ্গে সিঁচিত করা উচিত $scope = injectable.data'র, promise.then(..)' s, এবং $scope.complexClickAction = function() {..}এর

একটি বিকল্প পদ্ধতিতে ডেটা-decoupling এবং এইভাবে দেখার এনক্যাপস্যুলেশন একমাত্র স্থান, যে অর্জন করা হিসাবে এটা সত্যিই জ্ঞান করে তোলে মডেল থেকে দৃশ্য decouple করতে হয় একটি নির্দেশ দিয়ে । তবে সেখানেও, কার্যগুলিতে বা ফাংশনগুলিতে $watchস্ক্যালার মানগুলি না । এটি সময় সাশ্রয় করবে না বা কোডটিকে আর কোনও রক্ষণাবেক্ষণযোগ্য এবং পাঠযোগ্য নয়। এটি এমনকি টেস্টিংকে সহজ করে তুলবে না যেহেতু কৌণিক ক্ষেত্রে দৃust় পরীক্ষাগুলি সাধারণত ফলস্বরূপ DOM পরীক্ষা করে । পরিবর্তে, দিকনির্দেশক দাবিতে আপনার ডেটা এপিআই অবজেক্ট ফর্মে, এবং কেবলমাত্র এর দ্বারা নির্মিত এর ব্যবহার করে অনুগ্রহ করে ।controllerlink$watchng-bind


উদাহরণ http://plnkr.co/edit/MVeU1GKRTN4bqA3h9Yio

<body ng-app="ServiceNotification">
    <div style="border-style:dotted" ng-controller="TimerCtrl1">
        TimerCtrl1<br/>
        Bad:<br/>
        Last Updated: {{lastUpdated}}<br/>
        Last Updated: {{calls}}<br/>
        Good:<br/>
        Last Updated: {{data.lastUpdated}}<br/>
        Last Updated: {{data.calls}}<br/>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
    <script type="text/javascript">
        var app = angular.module("ServiceNotification", []);

        function TimerCtrl1($scope, Timer) {
            $scope.data = Timer.data;
            $scope.lastUpdated = Timer.data.lastUpdated;
            $scope.calls = Timer.data.calls;
        };

        app.factory("Timer", function ($timeout) {
            var data = { lastUpdated: new Date(), calls: 0 };

            var updateTimer = function () {
                data.lastUpdated = new Date();
                data.calls += 1;
                console.log("updateTimer: " + data.lastUpdated);

                $timeout(updateTimer, 500);
            };
            updateTimer();

            return {
                data: data
            };
        });
    </script>
</body>

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

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

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

  1. উদ্বেগের বিভাজন : কোনও উপাদান প্রপসের মাধ্যমে এর সমস্ত ডেটা গ্রাস করে এবং বিশ্বব্যাপী একক কণ্ঠস্বর (যেমন কৌণিক পরিষেবাগুলি) এর উপর অল্প নির্ভরতা রাখে না এবং ভিউ হায়ারার্কিতে এর উপরে কী ঘটেছিল সে সম্পর্কে কিছুই জানে না ।

  2. পরিবর্তনযোগ্যতা : সমস্ত প্রপসগুলি পরিবর্তনযোগ্য যা ডেটা পরিবর্তনের অকারণে ঝুঁকি দূর করে।

উপরের দুটি পয়েন্ট অর্জনের জন্য কৌণিক 2.0 এখন প্রতিক্রিয়া থেকে প্রচুর orrowণ নেওয়ার পথে।


1
আমি যত বেশি বুঝতে পারছি AngularJS এর ​​সাথে আরও কাজ করেছি working আমি বিশ্বাস করি যে AngularJS নিয়ন্ত্রণকারীরা যতটা সম্ভব সহজ এবং পাতলা হওয়া উচিত। নিয়ামকটিতে $ ঘড়ি যুক্ত করে এটি যুক্তিটিকে জটিল করে তোলে। কেবল পরিষেবাটিতে মান উল্লেখ করে এটি অনেক সহজ এবং এটি AngularJS উপায়ে আরও বেশি বলে মনে হয়। -
মাইক বারলো - বারদেভ

3
AngularJS এর ​​"দশ আদেশ"। এটি একটি কারণ হিসাবে ঘোষিত।
pilau

জোশ ডেভিড মিলারের উত্তর "ভুল" নয়। প্রত্যেক কিছুর জন্য একটি সময় এবং জায়গা রয়েছে।
জোশুয়া ডেভিড

আমি মনে করি আপনি ঠিক বলেছেন, @ ফায়ারকোডিং। আমি উত্তর আপডেট করার পরিকল্পনা করছি।
গিল বিরমন

@ গিলবিমান চমৎকার উত্তর। আপনি যদি নির্দেশনাটির জন্য লেখার উদাহরণ এবং উদাহরণ মনে করেন? আপনি যা বলেছেন তা চিত্রিত করার জন্য, "মডেল থেকে দৃষ্টিভঙ্গিটি বাস্তবে ডিক্লোল করার একমাত্র জায়গা হ'ল একটি নির্দেশের সাথে [[...] বরং, কোনও নির্দেশকের পরিবর্তে অবজেক্ট ফর্মে আপনার ডেটা এপিআই দাবি করুন এবং কেবলমাত্র $ এনজি-বাইন্ড দ্বারা নির্মিত প্রহরীগণ। "
ক্লোডে

78

আমার দৃষ্টিকোণ থেকে, $watchসেরা অনুশীলন উপায় হবে।

আপনি আসলে আপনার উদাহরণটি কিছুটা সহজ করতে পারেন:

function TimerCtrl1($scope, Timer) {
  $scope.$watch( function () { return Timer.data; }, function (data) {
    $scope.lastUpdated = data.lastUpdated;
    $scope.calls = data.calls;
  }, true);
}

আপনার এটাই দরকার।

যেহেতু বৈশিষ্ট্যগুলি একই সাথে আপডেট করা হয়, আপনার কেবল একটি ঘড়ি দরকার। এছাড়াও, যেহেতু এগুলি একটি একক নয় বরং ছোট একটি বস্তু থেকে এসেছে তাই আমি Timer.dataসম্পত্তিটি দেখার জন্য এটিকে পরিবর্তন করেছি । শেষ প্যারামিটারটি কেবল $watchরেফারেন্স একই কিনা তা নিশ্চিত করার চেয়ে গভীর সমতার জন্য চেক করতে বলেছিল।


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

সত্যি কথা বলতে, এখানে সম্ভবত একাধিক দৃষ্টিভঙ্গি রয়েছে এবং আমি অন্যান্য উত্তরের অপেক্ষায় রয়েছি।


3
আপনি কিছুটা ব্যাখ্যা করতে পারেন? পরিষেবাটি দেখার সাথে দর্শনটি কম সংযুক্ত হওয়ার কারণে আপনি কি ches ঘড়িগুলি পছন্দ করেন? {{lastUpdated}}{{timerData.lastUpdated}}
অর্থাত্

2
@ বারডেভ, Timer.dataএকটি $ ঘড়িতে ব্যবহার করার জন্য, $ স্কোপটিতে Timerসংজ্ঞায়িত করতে হবে, কারণ আপনি $ ঘড়িতে যে স্ট্রিং এক্সপ্রেশনটি পাস করেন তা সুযোগের বিপরীতে মূল্যায়ন করা হয়। এখানে একটি প্লাঙ্কার দেখায় যে কীভাবে সেই কাজটি করা যায়। ObjectEquality প্যারামিটার নথিভুক্ত করা এখানে - 3 য় প্যারামিটার - কিন্তু সত্যিই খুব ভাল না ব্যাখ্যা।
রাজকক

2
পারফরম্যান্স ওয়াইস, $watchবেশ অদক্ষ। স্ট্যাকওভারফ্লো . com / a
ক্রিম

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

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

19

পার্টিতে দেরীতে, তবে ভবিষ্যতের গুগলারের জন্য - সরবরাহিত উত্তরটি ব্যবহার করবেন না।

জাভাস্ক্রিপ্টে রেফারেন্স দ্বারা অবজেক্টগুলি পাস করার ব্যবস্থা রয়েছে, যখন এটি কেবল "সংখ্যা, স্ট্রিং ইত্যাদি" মানের জন্য অগভীর অনুলিপিটি পাস করে passes

উপরের উদাহরণে, কোনও পরিষেবার বাধ্যতামূলক বৈশিষ্ট্যের পরিবর্তে, কেন আমরা পরিষেবাটি সুযোগের মধ্যে প্রকাশ করি না?

$scope.hello = HelloService;

এই সহজ পদ্ধতির সাহায্যে কৌণিক দ্বি-মুখী বাঁধাই করতে সক্ষম হবে এবং আপনার প্রয়োজনীয় সমস্ত icalন্দ্রজালিক বিষয়গুলি তৈরি করবে। নজরদারি বা অপরিশোধিত মার্কআপ দিয়ে আপনার নিয়ামকটিকে হ্যাক করবেন না।

এবং যদি আপনি দুর্ঘটনাক্রমে আপনার পরিষেবা বৈশিষ্ট্যগুলিকে ওভাররাইট করার জন্য আপনার দৃষ্টিভঙ্গির বিষয়ে উদ্বিগ্ন definePropertyহন তবে এটিকে পঠনযোগ্য, গণনাযোগ্য, কনফিগারযোগ্য বা গেটার এবং সেটার সংজ্ঞায়িত করতে ব্যবহার করুন । আপনার পরিষেবাটিকে আরও দৃ solid় করে আপনি প্রচুর নিয়ন্ত্রণ অর্জন করতে পারেন।

চূড়ান্ত টিপ: আপনি যদি নিজের পরিষেবাদির চেয়ে আপনার নিয়ামকটিতে কাজ করার জন্য সময় ব্যয় করেন তবে আপনি এটি ভুল করছেন :(।

আপনি যে নির্দিষ্ট ডেমো কোড সরবরাহ করেছিলেন তাতে আমি আপনাকে সুপারিশ করব:

 function TimerCtrl1($scope, Timer) {
   $scope.timer = Timer;
 }
///Inside view
{{ timer.time_updated }}
{{ timer.other_property }}
etc...

সম্পাদনা:

আমি উপরে উল্লিখিত হিসাবে, আপনি ব্যবহার করে আপনার পরিষেবা বৈশিষ্ট্যের আচরণ নিয়ন্ত্রণ করতে পারেন defineProperty

উদাহরণ:

// Lets expose a property named "propertyWithSetter" on our service
// and hook a setter function that automatically saves new value to db !
Object.defineProperty(self, 'propertyWithSetter', {
  get: function() { return self.data.variable; },
  set: function(newValue) { 
         self.data.variable = newValue; 
         // let's update the database too to reflect changes in data-model !
         self.updateDatabaseWithNewData(data);
       },
  enumerable: true,
  configurable: true
});

এখন যদি আমাদের নিয়ামক হয়

$scope.hello = HelloService;
$scope.hello.propertyWithSetter = 'NEW VALUE';

আমাদের পরিষেবাটি propertyWithSetterকোনওভাবে ডাটাবেসে নতুন মানটির মান পরিবর্তন করে এবং পোস্ট করবে!

অথবা আমরা যে কোনও পদ্ধতির নিতে চাই।

এর জন্য MDN ডকুমেন্টেশন দেখুনdefineProperty


খুব নিশ্চিত যে এটি আমি উপরে বর্ণিয়ে যাচ্ছিলাম $scope.model = {timerData: Timer.data};, কেবল এটি সরাসরি স্কোপের পরিবর্তে মডেলটিতে সংযুক্ত করছি।
স্কট সিলভি 22'16

1
আফাইক, জেএস অবজেক্ট রেফারেন্স পরিষেবাতে সমস্ত কিছুর জন্য কাজ করে। এর মতো কোডিং: $ স্কোপ। কন্ট্রোলারভার = সার্ভিসবার, আপনি যা কিছু করেন $ স্কোপ.কন্ট্রোলারভারে সার্ভিয়ারেও সম্পন্ন হয়।
কাই ওয়াং

@ কাইওয়্যাং সম্মত হন, যদি না আপনি DefineAttribute ব্যবহার করার সিদ্ধান্ত নেন তবে আপনি নিয়ন্ত্রণ পরিষেবাদিগুলিকে আপনার পরিষেবা ডেটা পরিবর্তন করতে বাধা দিতে আপনার পরিষেবাগুলিতে একটি সেটার ফাংশন তৈরি করতে পারেন।
জালবোজা

12

আমি মনে করি এই প্রশ্নের একটি প্রাসঙ্গিক উপাদান রয়েছে।

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

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

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

একটি সতর্কতামূলক হিসাবে, আপনি সরাসরি আপনার $ সুযোগ বাইরে কোনও সম্পত্তি ঝুলানো উচিত নয় । $scopeপরিবর্তনশীল আপনার মডেল নয়। এটিতে আপনার মডেলের উল্লেখ রয়েছে।

আমার মনে, কেবল পরিষেবা থেকে নিচে তথ্য বিকিরণের জন্য "সেরা অনুশীলন" দেখুন:

function TimerCtrl1($scope, Timer) {
  $scope.model = {timerData: Timer.data};
};

এবং তারপরে আপনার ভিউতে অন্তর্ভুক্ত থাকবে {{model.timerData.lastupdated}}


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

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

6

উপরোক্ত উদাহরণগুলির উপর ভিত্তি করে আমি ভেবেছিলাম যে আমি কোনও নিয়ামক ভেরিয়েবলকে পরিষেবা ভেরিয়েবলের সাথে স্বচ্ছভাবে বাধ্য করতে পারি throw

নীচের উদাহরণে কন্ট্রোলার $scope.countভেরিয়েবলের পরিবর্তনগুলি স্বয়ংক্রিয়ভাবে পরিষেবা countভেরিয়েবলে প্রতিফলিত হবে ।

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

নীচের কোডটি http://jsfiddle.net/xuUHS/163/ এ কাজ করতে দেখা যায়

দেখুন:

<div ng-controller="ServiceCtrl">
    <p> This is my countService variable : {{count}}</p>
    <input type="number" ng-model="count">
    <p> This is my updated after click variable : {{countS}}</p>

    <button ng-click="clickC()" >Controller ++ </button>
    <button ng-click="chkC()" >Check Controller Count</button>
    </br>

    <button ng-click="clickS()" >Service ++ </button>
    <button ng-click="chkS()" >Check Service Count</button>
</div>

পরিষেবা / কন্ট্রোলার:

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

app.service('testService', function(){
    var count = 10;

    function incrementCount() {
      count++;
      return count;
    };

    function getCount() { return count; }

    return {
        get count() { return count },
        set count(val) {
            count = val;
        },
        getCount: getCount,
        incrementCount: incrementCount
    }

});

function ServiceCtrl($scope, testService)
{

    Object.defineProperty($scope, 'count', {
        get: function() { return testService.count; },
        set: function(val) { testService.count = val; },
    });

    $scope.clickC = function () {
       $scope.count++;
    };
    $scope.chkC = function () {
        alert($scope.count);
    };

    $scope.clickS = function () {
       ++testService.count;
    };
    $scope.chkS = function () {
        alert(testService.count);
    };

}

এটি একটি দুর্দান্ত সমাধান, আপনাকে ধন্যবাদ, এটি আমাকে অনেক সাহায্য করেছে, এটি করার খুব স্মার্ট উপায় :)
জাভিস পেরেজ

2

আমি মনে করি এটির বৈশিষ্ট্যগুলির পরিবর্তে পরিষেবাটিতে বাঁধাই এটি একটি সর্বোত্তম উপায় ।

কারণটা এখানে:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.7/angular.min.js"></script>
<body ng-app="BindToService">

  <div ng-controller="BindToServiceCtrl as ctrl">
    ArrService.arrOne: <span ng-repeat="v in ArrService.arrOne">{{v}}</span>
    <br />
    ArrService.arrTwo: <span ng-repeat="v in ArrService.arrTwo">{{v}}</span>
    <br />
    <br />
    <!-- This is empty since $scope.arrOne never changes -->
    arrOne: <span ng-repeat="v in arrOne">{{v}}</span>
    <br />
    <!-- This is not empty since $scope.arrTwo === ArrService.arrTwo -->
    <!-- Both of them point the memory space modified by the `push` function below -->
    arrTwo: <span ng-repeat="v in arrTwo">{{v}}</span>
  </div>

  <script type="text/javascript">
    var app = angular.module("BindToService", []);

    app.controller("BindToServiceCtrl", function ($scope, ArrService) {
      $scope.ArrService = ArrService;
      $scope.arrOne = ArrService.arrOne;
      $scope.arrTwo = ArrService.arrTwo;
    });

    app.service("ArrService", function ($interval) {
      var that = this,
          i = 0;
      this.arrOne = [];
      that.arrTwo = [];

      $interval(function () {
        // This will change arrOne (the pointer).
        // However, $scope.arrOne is still same as the original arrOne.
        that.arrOne = that.arrOne.concat([i]);

        // This line changes the memory block pointed by arrTwo.
        // And arrTwo (the pointer) itself never changes.
        that.arrTwo.push(i);
        i += 1;
      }, 1000);

    });
  </script>
</body> 

আপনি এই plunker এ এটি খেলতে পারেন ।


1

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


0

যে কোনও ডেটা বাঁধাই, যা পরিষেবা প্রেরণ করে তা কোনও ভাল ধারণা (আর্কিটেকচার) নয়, তবে আপনার যদি আর এটির প্রয়োজন হয় তবে আমি আপনাকে এটি করার 2 টি উপায়ের পরামর্শ দিচ্ছি

1) আপনি পরিষেবাটির ভিতরে না থাকা ডেটা পেতে পারেন You আপনি আপনার নিয়ামক / নির্দেশিকার অভ্যন্তরে ডেটা পেতে পারেন এবং এটি কোথাও আবদ্ধ করতে আপনার কোনও সমস্যা হবে না

২) আপনি কৌণিক ঘটনাগুলি ব্যবহার করতে পারেন you আপনি যখনই চান, আপনি একটি সিগন্যাল ($ রুটস্কোপ থেকে) প্রেরণ করতে পারেন এবং যেখানেই চান এটি ধরতে পারেন You এমনকি ইভেন্টের নামটিতে কোনও ডেটা প্রেরণ করতে পারেন।

হতে পারে এটি আপনাকে সহায়তা করতে পারে। উদাহরণগুলির সাথে আরও যদি আপনার প্রয়োজন হয় তবে এখানে লিঙ্কটি দিন

http://www.w3docs.com/snippets/angularjs/bind-value-between-service-and-controller-directive.html


-1

কি সম্পর্কে

scope = _.extend(scope, ParentScope);

কোথায় প্যারেন্টস্কোপ ইনজেকশন পরিষেবা?


-2

সর্বাধিক মার্জিত সমাধান ...

app.service('svc', function(){ this.attr = []; return this; });
app.controller('ctrl', function($scope, svc){
    $scope.attr = svc.attr || [];
    $scope.$watch('attr', function(neo, old){ /* if necessary */ });
});
app.run(function($rootScope, svc){
    $rootScope.svc = svc;
    $rootScope.$watch('svc', function(neo, old){ /* change the world */ });
});

এছাড়াও, আমি ইডিএগুলি লিখি (ইভেন্ট-চালিত আর্কিটেকচারস) তাই আমি নিম্নলিখিত [ওভারসিম্প্লিফাইড সংস্করণ] এর মতো কিছু করার প্রবণতা রাখি:

var Service = function Service($rootScope) {
    var $scope = $rootScope.$new(this);
    $scope.that = [];
    $scope.$watch('that', thatObserver, true);
    function thatObserver(what) {
        $scope.$broadcast('that:changed', what);
    }
};

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

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

আশাকরি এটা সাহায্য করবে...

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