কৌণিক - * এনজিআইফ বনাম সহজ ফাংশন কল টেমপ্লেটে


14

দুঃখিত যদি এটি ইতিমধ্যে এখানে উত্তর দেওয়া হয়েছে, তবে আমি আমাদের নির্দিষ্ট দৃশ্যের জন্য কোনও মিল খুঁজে পাইনি, সুতরাং এখানে যায়!

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

ধরা যাক আমাদের একটি টেমপ্লেট ব্লক রয়েছে যা একটি এনজিআইএফ দিয়ে জড়িয়ে আছে, এখানে একাধিক পরামিতি পরীক্ষা করে, যেমন:

<ng-template *ngIf="user && user.name && isAuthorized">
 ...
</ng-template>

এর মতো কিছুর তুলনায় পারফরম্যান্সে কি উল্লেখযোগ্য পার্থক্য থাকবে:

টেমপ্লেট:

<ng-template *ngIf="userCheck()">
 ...
</ng-template>

টাইপ করা বিষয়:

userCheck(): boolean {
  return this.user && this.user.name && this.isAuthorized;
}

সুতরাং প্রশ্নের সংক্ষিপ্তসার হিসাবে, শেষ বিকল্পটির কোনও উল্লেখযোগ্য পারফরম্যান্স ব্যয় হবে?

আমরা ২ য় পদ্ধতির ব্যবহার করতে পছন্দ করব, যেখানে আমাদের 2 টিরও বেশি শর্ত পরীক্ষা করতে হবে, তবে অনেকগুলি নিবন্ধ অনলাইনে বলে যে ফাংশন কলগুলি টেমপ্লেটগুলিতে সর্বদা খারাপ, তবে কি এই ক্ষেত্রে এটি আসলেই সমস্যা?


7
না, এটা হবে না। এটি আরও ক্লিনার, যেহেতু এটি টেমপ্লেটটিকে আরও পাঠযোগ্য, শর্তটি আরও সহজে পরীক্ষামূলক এবং পুনরায় ব্যবহারযোগ্য করে তোলে এবং এটিকে যতটা সম্ভব পঠনযোগ্য এবং দক্ষ করে তোলার জন্য আপনার কাছে আরও সরঞ্জাম (পুরো টাইপস্ক্রিপ্ট ভাষা) রয়েছে। যদিও আমি "ইউজারচেক" এর চেয়ে অনেক পরিষ্কার নামটি বেছে নেব।
জেবি নিজত

আপনার ইনপুট জন্য অনেক ধন্যবাদ :)
জেস্পার

উত্তর:


8

আমি যতটা সম্ভব টেম্পলেটগুলিতে ফাংশন কলগুলি এড়াতে চেষ্টা করেছি, তবে আপনার প্রশ্ন আমাকে দ্রুত গবেষণা করতে অনুপ্রাণিত করেছে:

আমি ক্যাশে userCheck()ফলাফলের সাথে আরও একটি মামলা যুক্ত করেছি

*ngIf="isUserChecked"

...
// .ts
isUserChecked = this.userCheck()

এখানে একটি ডেমো প্রস্তুত: https://stackblitz.com/edit/angular-9qgsm9

আশ্চর্যজনকভাবে দেখে মনে হচ্ছে এর মধ্যে কোনও পার্থক্য নেই

*ngIf="user && user.name && isAuthorized"

এবং

*ngIf="userCheck()"

...
// .ts
userCheck(): boolean {
  return this.user && this.user.name && this.isAuthorized;
}

এবং

*ngIf="isUserChecked"

...
// .ts
isUserChecked = this.userCheck()

এটি দেখে মনে হচ্ছে এটি কোনও সাধারণ সম্পত্তি যাচাইয়ের জন্য বৈধ, তবে কোনও asyncক্রিয়া, উদাহরণস্বরূপ কিছু এপিআইয়ের জন্য অপেক্ষা করা গেটারগুলির ক্ষেত্রে এটি অবশ্যই স্পষ্ট হবে difference


10

এটি একটি সুন্দর মতামত উত্তর।

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

আমি আরও মনে করি যে আপনার টেম্পলেটটিতে আপনার যা কিছু প্রকাশ রয়েছে তা পরিবর্তন সনাক্তকরণ ব্যবস্থার দ্বারা একটি ফাংশন হিসাবে মূল্যায়ন করা হবে, তাই আপনার টেমপ্লেটে বা আপনার উপাদান যুক্তিতে এটি রয়েছে কিনা তা বিবেচ্য নয়।

কেবল যুক্তিটি ফাংশনের ভিতরে ন্যূনতম রাখুন। আপনি যদি এই ধরনের কোনও ক্রিয়াকলাপের যে কোনও পারফরম্যান্সের প্রভাব সম্পর্কে সতর্ক হন তবে আমি আপনাকে দৃ strongly়ভাবে পরামর্শ দিচ্ছি যে আপনি যেভাবেই হোক সর্বোত্তম অনুশীলন হিসাবে বিবেচিত হন ChangeDetectionStrategyto OnPushএটির সাহায্যে, ফাংশনটি প্রতিটি চক্র বলা হবে না, কেবলমাত্র যখন Inputপরিবর্তন হয়, কোনও ইভেন্ট টেম্পলেটটির অভ্যন্তরে ঘটে থাকে ইত্যাদি etc.

(ইত্যাদি ব্যবহার করা, কারণ আমি অন্য কারণটি আর জানি না)


ব্যক্তিগতভাবে, আবারও, আমি মনে করি এটি পর্যবেক্ষণযোগ্য প্যাটার্নটি ব্যবহার করা আরও ভাল, আপনি তারপরে asyncপাইপটি ব্যবহার করতে পারেন এবং কেবলমাত্র যখন কোনও নতুন মান নির্গত হয়, টেমপ্লেটটি পুনরায় মূল্যায়ন করে:

userIsAuthorized$ = combineLatest([
  this.user$,
  this.isAuthorized$
]).pipe(
  map(([ user, authorized ]) => !!user && !!user.name && authorized),
  shareReplay({ refCount: true, bufferSize: 1 })
);

এরপরে আপনি কেবল টেমপ্লেটে এটি ব্যবহার করতে পারেন:

<ng-template *ngIf="userIsAuthorized$ | async">
 ...
</ng-template>

তবুও অন্য বিকল্পটি ব্যবহার করা হবে ngOnChanges, যদি উপাদানটির সমস্ত নির্ভরশীল ভেরিয়েবলগুলি ইনপুট হয় এবং নির্দিষ্ট টেম্পলেট ভেরিয়েবল গণনা করার জন্য আপনার অনেক যুক্তি রয়েছে (যা আপনি দেখিয়েছেন না):

export class UserComponent implements ngOnChanges {
  userIsAuthorized: boolean = false;

  @Input()
  user?: any;

  @Input()
  isAuthorized?: boolean;

  ngOnChanges(changes: SimpleChanges): void {
    if (changes.user || changes.isAuthorized) {
      this.userIsAuthorized = this.userCheck();
    }
  }

  userCheck(): boolean {
    return this.user && this.user.name && this.isAuthorized || false;
  }
}

যা আপনি আপনার টেম্পলেটটিতে এটি ব্যবহার করতে পারেন:

<ng-template *ngIf="userIsAuthorized">
 ...
</ng-template>

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

1
@ জেস্পার যদি উপাদানটি একটি অনুরোধ সম্পাদন করে তবে আপনার ইতিমধ্যে একটি Observableস্ট্রিম রয়েছে, যা এটি দেখানো ২ য় বিকল্পের জন্য একে একে নিখুঁত প্রার্থী করে তুলবে।
যাইহোক

6

অধ্যক্ষকে অনেক কারণে সুপারিশ করা হয় না:

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

যেহেতু কৌণিক পূর্বাভাস দিতে পারে না যে ব্যবহারকারীচেকের () রিটার্নের মান পরিবর্তিত হয়েছে কিনা, প্রতিবার পরিবর্তন সনাক্তকরণ চলাকালীন এটি ফাংশনটি সম্পাদন করা দরকার।

সুতরাং যদি পরিবর্তন সনাক্তকরণ 300 বার চলে, তবে ফাংশনটিকে 300 বার বলা হয়, এমনকি যদি তার ফেরতের মানটি কখনও পরিবর্তন হয় না।

এক্সটেন্ডেড ব্যাখ্যা এবং আরো সমস্যার https://medium.com/showpad-engineering/why-you-should-never-use-function-calls-in-angular-template-expressions-e1a50f9c0496

সমস্যাটি যখন আপনার উপাদানটি বড় হয় এবং অনেকগুলি পরিবর্তন ইভেন্টগুলিতে উপস্থিত হন তখন সমস্যাটি আসবে যদি আপনার উপাদানটি লিটল হয়ে যায় এবং কয়েকটি ইভেন্টে উপস্থিত হন তবে সমস্যা হবে না।

পর্যবেক্ষণযোগ্য সহ উদাহরণ

user$;
isAuth$
userCheck$;

userCheck$ = user$.pipe(
switchMap((user) => {
    return forkJoin([of(user), isAuth$]);
 }
)
.map(([user, isAuthenticated])=>{
   if(user && user.name && isAuthenticated){
     return true;
   } else {
     return false;
   }
})
);

তারপরে আপনি এটিকে কোড কোডে অ্যাসিঙ্ক পাইপ সহ পর্যবেক্ষণযোগ্য ব্যবহার করতে পারেন।


2
হাই, আমি কেবল এটি উল্লেখ করতে চেয়েছিলাম যে আমি ভেরিয়েবল ব্যবহারের পরামর্শটি গুরুতরভাবে বিভ্রান্তিকর বলে মনে করি .. সংযুক্ত মানগুলির কোনও পরিবর্তন হলে ভেরিয়েবলটি আপডেট হয় না
এনএসএনডিভিডি

1
এবং অভিব্যক্তিটি সরাসরি টেম্পলেটে রয়েছে কিনা, বা কোনও ফাংশন দ্বারা ফিরে এসেছে কিনা তা প্রতিটি পরিবর্তন সনাক্তকরণে মূল্যায়ন করতে হবে।
জেবি নিজাত

হ্যাঁ যে এর সত্যিকারের দুঃখিত খারাপ অভ্যাসগুলি না করার জন্য সম্পাদনা করবে
অ্যান্টনি উইলিস মুভিজ

@ অ্যান্টনিউইলিজমুওজ সুতরাং আপনি কীভাবে এমন পরিস্থিতির কাছে যাবেন? * এনজিআইএফ-তে একাধিক, হার্ড-টু-পঠন শর্তের সাথে কেবল বেঁচে থাকবেন?
জেস্পার

1
এটি আপনার পরিস্থিতির উপর নির্ভর করে আপনার কাছে মাঝারি পোস্টে কিছু বিকল্প রয়েছে। তবে আমি মনে করি আপনি পর্যবেক্ষণযোগ্য ব্যবহার করছেন। শর্ত হ্রাস করার জন্য একটি উদাহরণ সহ পোস্টটি সম্পাদনা করবে। আপনি যদি শর্তগুলি পান তবে কোথা থেকে আমাকে দেখাতে পারেন।
অ্যান্টনি উইলিস মুজোজ

0

আমি মনে করি যে জাভাস্ক্রিপ্টটি এমন একটি লক্ষ্য নিয়ে তৈরি করা হয়েছিল যাতে কোনও বিকাশকারী কোনও এক্সপ্রেসন এবং পারফরম্যান্স সম্পর্কিত কোনও ফাংশন কলের মধ্যে পার্থক্য লক্ষ্য না করে।

সি ++ inlineতে একটি ফাংশন চিহ্নিত করার জন্য একটি কীওয়ার্ড রয়েছে । উদাহরণ স্বরূপ:

inline bool userCheck()
{
    return isAuthorized;
}

এটি একটি ফাংশন কলকে বাদ দেওয়ার জন্য করা হয়েছিল। ফলস্বরূপ, সংকলক userCheckফাংশনটির বডির সাথে সমস্ত কলকে প্রতিস্থাপন করে। উদ্ভাবনের কারণ inline? একটি কর্মক্ষমতা বৃদ্ধি।

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

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