AngularJS: $ scope কল করার সময় ত্রুটি $ digest ইতিমধ্যে অগ্রগতি প্রতিরোধ করুন। $ প্রয়োগ()




angularjs-scope angular-digest (17)

এই প্যাটার্নটি ব্যবহার করবেন না - এটি সমাধান হওয়ার চেয়ে আরও বেশি ত্রুটি সৃষ্টি করবে। যদিও আপনি এটি নির্দিষ্ট কিছু মনে করেন, এটা না।

$digest $scope.$$phase চেক করে আপনি একটি $digest ইতিমধ্যে অগ্রগতি কিনা তা পরীক্ষা করতে পারেন।

if(!$scope.$$phase) {
  //$digest or $apply
}

$scope.$$phase "$apply" $digest বা $apply প্রগতিতে থাকলে "$digest" বা "$apply" ফিরে আসবে। আমি বিশ্বাস করি এই রাজ্যের মধ্যে পার্থক্য হল যে $digest বর্তমান সুযোগ এবং তার সন্তানদের ঘড়িগুলি প্রক্রিয়া করবে, এবং $apply সমস্ত স্কোপের দর্শকদের প্রক্রিয়া করবে।

@ ডিএনসি 253 এর বিন্দুতে, যদি আপনি নিজেকে $digest বা $apply ঘন ঘন কল $digest বলে থাকেন তবে আপনি এটি ভুল করছেন। আমি সাধারণত Angular এর নাগালের বাইরে একটি DOM ইভেন্ট অগ্নিসংযোগ ফলে আমি সুযোগ রাষ্ট্র আপডেট করার প্রয়োজন হলে আমি হজম করার প্রয়োজন। উদাহরণস্বরূপ, যখন একটি টুইটার বুটস্ট্র্যাপ মোডাল লুকানো হয়। কখনও কখনও DOM ইভেন্টটি যখন $digest প্রগতিতে থাকে, তখন তা কখনও কখনও হয় না। এজন্যই আমি এই চেকটি ব্যবহার করি।

কেউ যদি জানে যে আমি ভালো উপায় জানতে চাই।

মন্তব্য থেকে: @anddoutoi দ্বারা

angular.js এন্টি প্যাটার্নস

  1. if (!$scope.$$phase) $scope.$apply() না if (!$scope.$$phase) $scope.$apply() , এটি আপনার $scope.$apply() কল স্ট্যাকে যথেষ্ট উচ্চ নয়।

আমি যে কৌণিক একটি অ্যাপ্লিকেশন নির্মাণের পরে আমার স্কোপ ম্যানুয়ালি আমার পৃষ্ঠা আপডেট করতে হবে যে খুঁজে পাচ্ছি।

আমি এটি করতে একমাত্র উপায় হল আমার নিয়ামক এবং নির্দেশিকার সুযোগ থেকে $apply() কল $apply() । এর সাথে সমস্যা হল যে এটি কনসোলে একটি ত্রুটি নিক্ষেপ করে যা পড়ে:

ত্রুটি: $ হজম ইতিমধ্যে অগ্রগতি

যে কেউ এই ত্রুটি এড়ানো বা একই জিনিস অর্জন কিন্তু কিভাবে একটি ভিন্ন উপায়ে জানেন?


yearofmoo একটি reusable $ নিরাপদ তৈরি একটি মহান কাজ করেনি আমাদের জন্য ফাংশন প্রয়োগ করুন:

https://github.com/yearofmoo/AngularJS-Scope.SafeApply

ব্যবহার:

//use by itself
$scope.$safeApply();

//tell it which scope to update
$scope.$safeApply($scope);
$scope.$safeApply($anotherScope);

//pass in an update function that gets called when the digest is going on...
$scope.$safeApply(function() {

});

//pass in both a scope and a function
$scope.$safeApply($anotherScope,function() {

});

//call it on the rootScope
$rootScope.$safeApply();
$rootScope.$safeApply($rootScope);
$rootScope.$safeApply($scope);
$rootScope.$safeApply($scope, fn);
$rootScope.$safeApply(fn);


আপনি যদি এই ভাবে ব্যবহার করেন তবে কখনও কখনও আপনি এখনও ত্রুটি পাবেন ( https://.com/a/12859093/801426 )।

এটা চেষ্টা কর:

if(! $rootScope.$root.$$phase) {
...

আমি এই পদ্ধতি ব্যবহার করা হয়েছে এবং এটা পুরোপুরি জরিমানা কাজ বলে মনে হয়। এই চক্রটি শেষ হওয়ার সময়টি অপেক্ষা করে এবং তারপরে ট্রিগারগুলি apply() । ফাংশন কল করুন apply(<your scope>) আপনি চান যে কোন জায়গায় থেকে।

function apply(scope) {
  if (!scope.$$phase && !scope.$root.$$phase) {
    scope.$apply();
    console.log("Scope Apply Done !!");
  } 
  else {
    console.log("Scheduling Apply after 200ms digest cycle already in progress");
    setTimeout(function() {
        apply(scope)
    }, 200);
  }
}

আমি এই সমস্যাটি সমাধান করতে সক্ষম হচ্ছি $eval কল করার পরিবর্তে $apply যেখানে আমি জানি যে $digest ফাংশন চলবে।

docs অনুযায়ী, $apply মূলত এই কাজ করে:

function $apply(expr) {
  try {
    return $eval(expr);
  } catch (e) {
    $exceptionHandler(e);
  } finally {
    $root.$digest();
  }
}

আমার ক্ষেত্রে, একটি ng-click একটি সুযোগের মধ্যে একটি পরিবর্তনশীল পরিবর্তন করে, এবং ঐ পরিবর্তনশীলটির $ ঘড়ি অন্যান্য পরিবর্তনগুলি পরিবর্তন করে যা $applied । এই শেষ পদক্ষেপটি "ডাইজেস্ট ইতিমধ্যে অগ্রগতি" ত্রুটির কারণ করে।

ঘড়ি অভিব্যক্তিটির ভিতরে $eval সাথে $apply প্রতিস্থাপনের সুযোগটি প্রত্যাশিত হিসাবে আপডেট হয়ে যায়।

অতএব, এটি প্রদর্শিত হয় যে যদি কোঙ্গলটি যে কোনওভাবে চলতে থাকে তবে কৌণিকের মধ্যে অন্য কোন পরিবর্তনের কারণে, $eval ing শুধুমাত্র আপনাকে যা করতে হবে।


উপরের উত্তরগুলির অনুরূপ কিন্তু এটি আমার জন্য বিশ্বস্তভাবে কাজ করেছে ... একটি পরিষেবাতে যোগ করুন:

    //sometimes you need to refresh scope, use this to prevent conflict
    this.applyAsNeeded = function (scope) {
        if (!scope.$$phase) {
            scope.$apply();
        }
    };

এই আপনার সমস্যা সমাধান করা হবে:

if(!$scope.$$phase) {
  //TODO
}

এই প্রক্রিয়া রাখা হ্যান্ডি সামান্য সাহায্যকারী পদ্ধতি DRY:

function safeApply(scope, fn) {
    (scope.$$phase || scope.$root.$$phase) ? fn() : scope.$apply(fn);
}

এই বিষয়টিতে কৌণিক ছেলের সাথে সাম্প্রতিক আলোচনা থেকে: ভবিষ্যতের-প্রমাণীকরণের কারণে, আপনি $$phase ব্যবহার করতে পারবেন না

এটি করার জন্য "ডান" উপায়টি চাপলে, উত্তরটি বর্তমানে হয়

$timeout(function() {
  // anything you want can go here and will safely be run on the next digest.
})

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

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

window.gapi.client.load('oauth2', 'v2', function() {
    var request = window.gapi.client.oauth2.userinfo.get();
    request.execute(function(response) {
        // This happens outside of angular land, so wrap it in a timeout 
        // with an implied apply and blammo, we're in action.
        $timeout(function() {
            if(typeof(response['error']) !== 'undefined'){
                // If the google api sent us an error, reject the promise.
                deferred.reject(response);
            }else{
                // Resolve the promise with the whole response if ok.
                deferred.resolve(response);
            }
        });
    });
});

$ Timeout এর জন্য বিলম্বের যুক্তিটি ঐচ্ছিক এবং 0 টি ডিফল্ট থাকলে সেটিকে ডিফল্ট করা হবে ( $timeout $browser.defer কল করে। ডিফল্ট সেট না থাকলে ডিফল্ট 0 তে নির্ধারণ করুন )

একটু অজ্ঞান, কিন্তু যে কেউ Angular লেখা ছেলেরা এর উত্তর, তাই এটা আমার জন্য যথেষ্ট ভাল!


এটি পাওয়া গেল: https://coderwall.com/p/ngisma যেখানে নাথান ওয়াকার (পৃষ্ঠাটির নিচের অংশে) $ rootScope এ একটি সজ্জাকারীকে প্রস্তাব করে 'funApply' তৈরি করার জন্য কোডটি:

yourAwesomeModule.config([
  '$provide', function($provide) {
    return $provide.decorator('$rootScope', [
      '$delegate', function($delegate) {
        $delegate.safeApply = function(fn) {
          var phase = $delegate.$$phase;
          if (phase === "$apply" || phase === "$digest") {
            if (fn && typeof fn === 'function') {
              fn();
            }
          } else {
            $delegate.$apply(fn);
          }
        };
        return $delegate;
      }
    ]);
  }
]);

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

$timeout(function(){
    //any code in here will automatically have an apply run afterwards
});

অথবা যদি আপনি আন্ডারস্কোর আছে:

_.defer(function(){$scope.$apply();});

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


নিরাপদ $apply সংক্ষিপ্ততম ফর্ম:

$timeout(angular.noop)

বুঝতে _.defer যে কৌণিক নথিগুলি $$phase বিরোধী-প্যাটার্নটি চেক করে কল করে , আমি $timeout পেতে এবং _.defer করতে কাজ করার চেষ্টা করেছিলাম।

টাইমআউট এবং স্থগিত পদ্ধতিগুলি FOUT মতো {{myVar}} অস্পষ্ট {{myVar}} সামগ্রীর ফ্ল্যাশ তৈরি করে। আমার জন্য এই গ্রহণযোগ্য ছিল না। এটা অনেকটা ছাড়া আমাকে ছেড়ে দেয় যা ড্যাটামেটিকাল বলে যে কিছু একটা হ্যাক, এবং কোন উপযুক্ত বিকল্প নেই।

প্রত্যেক সময় কাজ করে যে একমাত্র জিনিস হল:

if(scope.$$phase !== '$digest'){ scope.$digest() }

আমি এই পদ্ধতির বিপদ বুঝতে পারছি না, কেন এটি মন্তব্য এবং কৌণিক দলের মানুষের দ্বারা হ্যাক হিসাবে বর্ণনা করা হয়েছে। কমান্ড সুনির্দিষ্ট এবং পড়তে সহজ মনে হয়:

"যদি এক ইতিমধ্যে ঘটছে না হজম না"

কফিস্ক্রিপ্টে এটি এমনকি prettier:

scope.$digest() unless scope.$$phase is '$digest'

এই সমস্যা কি? একটি বিকল্প আছে যে একটি FOUT তৈরি হবে না? https://github.com/yearofmoo/AngularJS-Scope.SafeApply জরিমানা দেখায় তবে $$phase পরিদর্শন পদ্ধতিও ব্যবহার করে।


যখন আপনি এই ত্রুটিটি পান, তখন এটি মূলত মানে যে এটি ইতিমধ্যে আপনার দৃশ্য আপডেট করার প্রক্রিয়াতে রয়েছে। আপনি আপনার নিয়ামক মধ্যে $apply() কল করতে হবে না। যদি আপনার দৃশ্যটি আপনার প্রত্যাশিত হিসাবে আপডেট না হয়, এবং তারপরে আপনি $apply() কল $apply() পরে এই ত্রুটিটি পান তবে এটি সম্ভবত আপনি মডেলটি সঠিকভাবে আপডেট করছেন না। আপনি কিছু নির্দিষ্ট পোস্ট পোস্ট, আমরা কোর সমস্যা খুঁজে বের করতে পারে।


সব প্রথম, এই ভাবে ঠিক করবেন না

if ( ! $scope.$$phase) { 
  $scope.$apply(); 
}

এটি অর্থহীন নয় কারণ $ ফেজটি $ ডাইজেস্ট চক্রের জন্য একটি বুলিয়ান পতাকা মাত্র, তাই আপনার $ প্রয়োগ (কখনও কখনও চালানো হবে না)। এবং এটি একটি খারাপ অনুশীলন মনে রাখবেন।

পরিবর্তে, $timeout ব্যবহার করুন

    $timeout(function(){ 
  // Any code in here will automatically have an $scope.apply() run afterwards 
$scope.myvar = newValue; 
  // And it just works! 
});

আপনি যদি আন্ডারস্কোর বা লোডশ ব্যবহার করেন তবে আপনি defer () ব্যবহার করতে পারেন:

_.defer(function(){ 
  $scope.$apply(); 
});

$scope.$$phase || $scope.$apply(); ব্যবহার করুন $scope.$$phase || $scope.$apply(); $scope.$$phase || $scope.$apply(); পরিবর্তে





angular-digest