দীর্ঘ কাজ অপ্টিমাইজ করুন

তোমাকে বলা হয়েছে "মূল থ্রেডটি ব্লক করো না" এবং "তোমার দীর্ঘ কাজগুলো ভেঙে ফেলো", কিন্তু এই কাজগুলো করার অর্থ কী?

প্রকাশিত: ৩০ সেপ্টেম্বর, ২০২২, সর্বশেষ আপডেট: ১৯ ডিসেম্বর, ২০২৪

জাভাস্ক্রিপ্ট অ্যাপগুলিকে দ্রুত রাখার জন্য সাধারণ পরামর্শগুলি সাধারণত নিম্নলিখিত পরামর্শগুলির উপর নির্ভর করে:

  • "মূল থ্রেডটি ব্লক করবেন না।"
  • "তোমার লম্বা কাজগুলো ভেঙে ফেলো।"

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

জাভাস্ক্রিপ্টে কাজগুলি কীভাবে অপ্টিমাইজ করতে হয় তা বোঝার জন্য, আপনাকে প্রথমে জানতে হবে কাজগুলি কী এবং ব্রাউজার কীভাবে সেগুলি পরিচালনা করে।

কাজ কী?

টাস্ক হলো ব্রাউজার দ্বারা করা যেকোনো বিচ্ছিন্ন কাজ। এই কাজের মধ্যে রয়েছে রেন্ডারিং, HTML এবং CSS পার্সিং, জাভাস্ক্রিপ্ট চালানো এবং অন্যান্য ধরণের কাজ যা আপনার সরাসরি নিয়ন্ত্রণে নাও থাকতে পারে। এই সবকিছুর মধ্যে, আপনার লেখা জাভাস্ক্রিপ্ট সম্ভবত কাজের সবচেয়ে বড় উৎস।

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

জাভাস্ক্রিপ্টের সাথে সম্পর্কিত কাজগুলি কয়েকটি উপায়ে কর্মক্ষমতাকে প্রভাবিত করে:

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

এই সমস্ত জিনিস - ওয়েব ওয়ার্কার এবং অনুরূপ API গুলি বাদে - মূল থ্রেডে ঘটে।

মূল থ্রেড কী?

মূল থ্রেড হলো যেখানে বেশিরভাগ কাজ ব্রাউজারে চলে এবং যেখানে আপনার লেখা প্রায় সমস্ত জাভাস্ক্রিপ্ট কার্যকর করা হয়।

মূল থ্রেড একবারে কেবল একটি কাজ প্রক্রিয়া করতে পারে। ৫০ মিলিসেকেন্ডের বেশি সময় নেয় এমন যেকোনো কাজ দীর্ঘ কাজ । ৫০ মিলিসেকেন্ডের বেশি সময় নেয় এমন কাজের জন্য, টাস্কের মোট সময় ৫০ মিলিসেকেন্ড বিয়োগ করলে তাকে টাস্কের ব্লকিং পিরিয়ড বলা হয়।

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

Chrome এর DevTools এর পারফরম্যান্স প্রোফাইলারে একটি দীর্ঘ কাজ। টাস্কের ব্লকিং অংশ (৫০ মিলিসেকেন্ডের বেশি) লাল তির্যক ডোরাকাটা প্যাটার্ন দিয়ে চিত্রিত করা হয়েছে।
Chrome এর পারফরম্যান্স প্রোফাইলারে দেখানো একটি দীর্ঘ কাজ। দীর্ঘ কাজগুলি টাস্কের কোণে একটি লাল ত্রিভুজ দ্বারা নির্দেশিত হয়, টাস্কের ব্লকিং অংশটি তির্যক লাল ডোরাকাটা প্যাটার্ন দিয়ে পূর্ণ থাকে।

মূল থ্রেডটি যাতে বেশিক্ষণ ব্লক না থাকে, তার জন্য আপনি একটি দীর্ঘ কাজকে কয়েকটি ছোট ছোট কাজয় ভাগ করতে পারেন।

একটি দীর্ঘ কাজ বনাম একই কাজকে ছোট ছোট কাজে ভাগ করা হয়েছে। দীর্ঘ কাজটি একটি বৃহৎ আয়তক্ষেত্র, যেখানে খণ্ডিত কাজটি পাঁচটি ছোট বাক্স যা সম্মিলিতভাবে দীর্ঘ কাজের প্রস্থের সমান।
একটি দীর্ঘ কাজের সাথে একই কাজের পাঁচটি ছোট কাজে বিভক্ত একটি দৃশ্যায়ন।

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

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

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

এখন যেহেতু আপনি জানেন কেন কাজগুলিকে ভাগ করা গুরুত্বপূর্ণ, আপনি জাভাস্ক্রিপ্টে এটি কীভাবে করবেন তা শিখতে পারেন।

কার্য ব্যবস্থাপনা কৌশল

সফটওয়্যার আর্কিটেকচারের একটি সাধারণ পরামর্শ হল আপনার কাজকে ছোট ছোট ফাংশনে ভাগ করা:

function saveSettings () {
  validateForm();
  showSpinner();
  saveToDatabase();
  updateUI();
  sendAnalytics();
}

এই উদাহরণে, saveSettings() নামে একটি ফাংশন আছে যা একটি ফর্ম যাচাই করতে, একটি স্পিনার দেখাতে, অ্যাপ্লিকেশন ব্যাকএন্ডে ডেটা পাঠাতে, ব্যবহারকারী ইন্টারফেস আপডেট করতে এবং বিশ্লেষণ পাঠাতে পাঁচটি ফাংশন কল করে।

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

তবে এখানে একটি সম্ভাব্য সমস্যা হল, জাভাস্ক্রিপ্ট এই ফাংশনগুলির প্রতিটিকে আলাদা আলাদা কাজ হিসেবে চালায় না কারণ এগুলি saveSettings() ফাংশনের মধ্যে কার্যকর করা হয়। এর অর্থ হল পাঁচটি ফাংশনই একটি কাজ হিসেবে চলবে।

Chrome এর পারফরম্যান্স প্রোফাইলারে দেখানো saveSettings ফাংশন। যদিও শীর্ষ-স্তরের ফাংশনটি আরও পাঁচটি ফাংশনকে কল করে, সমস্ত কাজ একটি দীর্ঘ টাস্কে সঞ্চালিত হয় যার ফলে ফাংশনটি চালানোর ব্যবহারকারী-দৃশ্যমান ফলাফল দৃশ্যমান হয় না যতক্ষণ না সমস্ত সম্পূর্ণ হয়।
একটি একক ফাংশন saveSettings() যা পাঁচটি ফাংশন কল করে। কাজটি একটি দীর্ঘ একঘেয়ে কাজের অংশ হিসাবে পরিচালিত হয়, পাঁচটি ফাংশন সম্পূর্ণ না হওয়া পর্যন্ত যেকোনো ভিজ্যুয়াল প্রতিক্রিয়াকে ব্লক করে।

সবচেয়ে ভালো ক্ষেত্রে, এমনকি এই ফাংশনগুলির মধ্যে একটিও কাজের মোট দৈর্ঘ্যে ৫০ মিলিসেকেন্ড বা তার বেশি অবদান রাখতে পারে। সবচেয়ে খারাপ ক্ষেত্রে, এই কাজগুলির আরও অনেক বেশি সময় ধরে চলতে পারে - বিশেষ করে সম্পদ-সীমাবদ্ধ ডিভাইসগুলিতে।

এই ক্ষেত্রে, saveSettings() ব্যবহারকারীর ক্লিকের মাধ্যমে ট্রিগার হয়, এবং যেহেতু সম্পূর্ণ ফাংশনটি চালানো শেষ না হওয়া পর্যন্ত ব্রাউজার কোনও প্রতিক্রিয়া দেখাতে সক্ষম হয় না, তাই এই দীর্ঘ কাজের ফলে একটি ধীর এবং প্রতিক্রিয়াহীন UI তৈরি হয় এবং এটি Next Paint (INP) এর সাথে একটি দুর্বল ইন্টারঅ্যাকশন হিসাবে পরিমাপ করা হবে।

কোড এক্সিকিউশন ম্যানুয়ালি পিছিয়ে দিন

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

ডেভেলপাররা কাজগুলিকে ছোট ছোট ভাগে ভাগ করার জন্য যে পদ্ধতিটি ব্যবহার করেছেন তা হল setTimeout() । এই কৌশলের সাহায্যে, আপনি ফাংশনটি setTimeout() এ পাস করেন। এটি কলব্যাকের এক্সিকিউশনকে একটি পৃথক টাস্কে স্থগিত করে, এমনকি যদি আপনি 0 এর টাইমআউট নির্দিষ্ট করেন।

function saveSettings () {
  // Do critical work that is user-visible:
  validateForm();
  showSpinner();
  updateUI();

  // Defer work that isn't user-visible to a separate task:
  setTimeout(() => {
    saveToDatabase();
    sendAnalytics();
  }, 0);
}

এটি yielding নামে পরিচিত, এবং এটি ধারাবাহিকভাবে চালানোর জন্য প্রয়োজনীয় ফাংশনগুলির একটি সিরিজের জন্য সবচেয়ে ভালো কাজ করে।

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

function processData () {
  for (const item of largeDataArray) {
    // Process the individual item here.
  }
}

ডেভেলপারের এরগনোমিক্সের কারণে এখানে setTimeout() ব্যবহার করা সমস্যাযুক্ত, এবং নেস্টেড setTimeout() এর পাঁচ রাউন্ডের পরে, ব্রাউজার প্রতিটি অতিরিক্ত setTimeout() এর জন্য সর্বনিম্ন 5 মিলিসেকেন্ড বিলম্ব আরোপ করা শুরু করবে।

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

একটি ডেডিকেটেড ইল্ডিং API: scheduler.yield()

Browser Support

  • ক্রোম: ১২৯।
  • প্রান্ত: ১২৯।
  • ফায়ারফক্স: ১৪২।
  • সাফারি: সমর্থিত নয়।

Source

scheduler.yield() হল একটি API যা বিশেষভাবে ব্রাউজারের মূল থ্রেডে ইল্ড করার জন্য ডিজাইন করা হয়েছে।

এটি ভাষা-স্তরের সিনট্যাক্স বা কোনও বিশেষ গঠন নয়; scheduler.yield() কেবল একটি ফাংশন যা একটি Promise প্রদান করে যা ভবিষ্যতের কোনও কাজে সমাধান করা হবে। সেই Promise পরে চালানোর জন্য চেইন করা যেকোনো কোড সমাধান করা হয়েছে (হয় একটি স্পষ্ট .then() শৃঙ্খলে অথবা একটি অ্যাসিঙ্ক ফাংশনে এটি await করার পরে) তারপর সেই ভবিষ্যতের কার্যে চালানো হবে।

বাস্তবে: একটি await scheduler.yield() সন্নিবেশ করান এবং ফাংশনটি সেই সময়ে এক্সিকিউশন থামিয়ে মূল থ্রেডে চলে যাবে। ফাংশনের বাকি অংশের এক্সিকিউশন - যাকে ফাংশনের ধারাবাহিকতা বলা হয় - একটি নতুন ইভেন্ট-লুপ টাস্কে চালানোর জন্য নির্ধারিত হবে। যখন সেই টাস্কটি শুরু হবে, তখন প্রতীক্ষিত প্রতিশ্রুতিটি সমাধান করা হবে এবং ফাংশনটি যেখানে শেষ হয়েছিল সেখানেই এক্সিকিউশন চালিয়ে যাবে।

async function saveSettings () {
  // Do critical work that is user-visible:
  validateForm();
  showSpinner();
  updateUI();

  // Yield to the main thread:
  await scheduler.yield()

  // Work that isn't user-visible, continued in a separate task:
  saveToDatabase();
  sendAnalytics();
}
Chrome এর পারফরম্যান্স প্রোফাইলারে দেখানো saveSettings ফাংশনটি এখন দুটি কাজে বিভক্ত। প্রথম টাস্কটি দুটি ফাংশন কল করে, তারপর ফল দেয়, যা লেআউট এবং পেইন্টের কাজ সম্পাদন করতে দেয় এবং ব্যবহারকারীকে একটি দৃশ্যমান প্রতিক্রিয়া দেয়। ফলস্বরূপ, ক্লিক ইভেন্টটি অনেক দ্রুত 64 মিলিসেকেন্ডে শেষ হয়। দ্বিতীয় টাস্কটি শেষ তিনটি ফাংশন কল করে।
saveSettings() ফাংশনটির সম্পাদন এখন দুটি কাজে বিভক্ত। ফলস্বরূপ, লেআউট এবং পেইন্ট দুটি কাজের মধ্যে চলতে পারে, যা ব্যবহারকারীকে দ্রুত ভিজ্যুয়াল প্রতিক্রিয়া দেয়, যা এখন অনেক ছোট পয়েন্টার ইন্টারঅ্যাকশন দ্বারা পরিমাপ করা হয়।

অন্যান্য ফলনশীল পদ্ধতির তুলনায় scheduler.yield() এর আসল সুবিধা হল এর ধারাবাহিকতা অগ্রাধিকার পায়, যার অর্থ হল যদি আপনি কোনও কাজের মাঝখানে ফলন দেন, তাহলে অন্যান্য অনুরূপ কাজ শুরু হওয়ার আগেই বর্তমান কাজের ধারাবাহিকতা চলে যাবে।

এটি অন্যান্য টাস্ক সোর্স থেকে আসা কোডগুলিকে আপনার কোডের সম্পাদনের ক্রম, যেমন তৃতীয় পক্ষের স্ক্রিপ্ট থেকে আসা কাজগুলিকে বাধাগ্রস্ত করা থেকে বিরত রাখে।

তিনটি চিত্রে ফলন, ফলন এবং ফলন এবং ধারাবাহিকতা ছাড়া কাজগুলি দেখানো হয়েছে। ফলন ছাড়া দীর্ঘ কাজ রয়েছে। ফলন সহ, আরও বেশি কাজ রয়েছে যা ছোট, কিন্তু অন্যান্য সম্পর্কহীন কাজের দ্বারা বাধাগ্রস্ত হতে পারে। ফলন এবং ধারাবাহিকতা সহ, আরও বেশি কাজ রয়েছে যা ছোট, কিন্তু তাদের সম্পাদনের ক্রম সংরক্ষিত রয়েছে।
যখন আপনি scheduler.yield() ব্যবহার করেন, তখন অন্যান্য কাজে যাওয়ার আগে ধারাবাহিকতা যেখানে শেষ হয়েছিল সেখান থেকে শুরু হয়।

ক্রস-ব্রাউজার সাপোর্ট

scheduler.yield() এখনও সকল ব্রাউজারে সমর্থিত নয়, তাই একটি ফলব্যাক প্রয়োজন।

একটি সমাধান হল আপনার বিল্ডে scheduler-polyfill ড্রপ করা, এবং তারপর scheduler.yield() সরাসরি ব্যবহার করা যেতে পারে; পলিফিল অন্যান্য টাস্ক-শিডিউলিং ফাংশনগুলিতে ফিরে যাওয়া পরিচালনা করবে যাতে এটি ব্রাউজারগুলিতে একইভাবে কাজ করে।

বিকল্পভাবে, একটি কম পরিশীলিত সংস্করণ কয়েকটি লাইনে লেখা যেতে পারে, যদি scheduler.yield() উপলব্ধ না থাকে তবে শুধুমাত্র প্রতিশ্রুতিতে মোড়ানো setTimeout ব্যবহার করে ফলব্যাক হিসাবে ব্যবহার করা যেতে পারে।

function yieldToMain () {
  if (globalThis.scheduler?.yield) {
    return scheduler.yield();
  }

  // Fall back to yielding with setTimeout.
  return new Promise(resolve => {
    setTimeout(resolve, 0);
  });
}

scheduler.yield() সাপোর্ট ছাড়া ব্রাউজারগুলি অগ্রাধিকারপ্রাপ্ত ধারাবাহিকতা পাবে না, তবুও ব্রাউজারটি প্রতিক্রিয়াশীল থাকার জন্য এগুলি ফল দেবে।

পরিশেষে, এমন কিছু ক্ষেত্রে থাকতে পারে যেখানে আপনার কোডটি মূল থ্রেডে ইল্ড করতে পারবে না যদি এর ধারাবাহিকতা অগ্রাধিকার না দেওয়া হয় (উদাহরণস্বরূপ, একটি পরিচিত-ব্যস্ত পৃষ্ঠা যেখানে ইল্ডিং কিছু সময়ের জন্য কাজ সম্পূর্ণ না করার ঝুঁকি রাখে)। সেই ক্ষেত্রে, scheduler.yield() এক ধরণের প্রগতিশীল বর্ধন হিসাবে বিবেচনা করা যেতে পারে: যেখানে scheduler.yield() উপলব্ধ রয়েছে এমন ব্রাউজারগুলিতে yield, অন্যথায় চালিয়ে যান।

এটি বৈশিষ্ট্য সনাক্তকরণ এবং একটি সহজ ওয়ান-লাইনারে একটি একক মাইক্রোটাস্কের জন্য অপেক্ষা করার মাধ্যমে করা যেতে পারে:

// Yield to the main thread if scheduler.yield() is available.
await globalThis.scheduler?.yield?.();

scheduler.yield() দিয়ে দীর্ঘদিনের কাজ ভেঙে ফেলুন

scheduler.yield() ব্যবহারের এই পদ্ধতিগুলির যেকোনো একটি ব্যবহারের সুবিধা হল আপনি যেকোনো async ফাংশনে এটি await করতে পারবেন।

উদাহরণস্বরূপ, যদি আপনার এমন কিছু কাজ থাকে যা প্রায়শই দীর্ঘ কাজ করে, তাহলে আপনি কাজটি ভাগ করে নেওয়ার জন্য yields সন্নিবেশ করতে পারেন।

async function runJobs(jobQueue) {
  for (const job of jobQueue) {
    // Run the job:
    job();

    // Yield to the main thread:
    await yieldToMain();
  }
}

runJobs() এর ধারাবাহিকতা অগ্রাধিকার পাবে, তবে ব্যবহারকারীর ইনপুটকে দৃশ্যত সাড়া দেওয়ার মতো উচ্চ-অগ্রাধিকারের কাজ চালানোর অনুমতি দেবে, যাতে কাজের দীর্ঘ তালিকা শেষ হওয়ার জন্য অপেক্ষা করতে না হয়।

তবে, এটি yielding-এর একটি দক্ষ ব্যবহার নয়। scheduler.yield() দ্রুত এবং দক্ষ, তবে এর কিছু ওভারহেড আছে। যদি jobQueue এর কিছু কাজ খুব কম হয়, তাহলে ওভারহেড দ্রুত প্রকৃত কাজ সম্পাদনের চেয়ে Yielding এবং পুনরায় শুরু করার জন্য বেশি সময় ব্যয় করতে পারে।

একটি পদ্ধতি হল কাজগুলিকে ব্যাচ করা, শুধুমাত্র যদি শেষ ইল্ডের পর থেকে যথেষ্ট সময় হয়ে থাকে তবেই তাদের মধ্যে ইল্ডিং করা। কাজগুলিকে দীর্ঘ কাজ থেকে বিরত রাখার জন্য একটি সাধারণ সময়সীমা হল ৫০ মিলিসেকেন্ড, তবে এটি প্রতিক্রিয়াশীলতা এবং কাজের সারি সম্পূর্ণ করার সময়ের মধ্যে একটি বিনিময় হিসাবে সামঞ্জস্য করা যেতে পারে।

async function runJobs(jobQueue, deadline=50) {
  let lastYield = performance.now();

  for (const job of jobQueue) {
    // Run the job:
    job();

    // If it's been longer than the deadline, yield to the main thread:
    if (performance.now() - lastYield > deadline) {
      await yieldToMain();
      lastYield = performance.now();
    }
  }
}

ফলস্বরূপ, কাজগুলি ভেঙে ফেলা হয় এবং রান করতে খুব বেশি সময় লাগে না, তবে রানারটি প্রতি ৫০ মিলিসেকেন্ডে কেবল মূল থ্রেডে পৌঁছায়।

Chrome DevTools পারফর্ম্যান্স প্যানেলে দেখানো জব ফাংশনের একটি সিরিজ, যার সম্পাদন একাধিক কাজের উপর বিভক্ত।
কাজগুলো একাধিক কাজে বিভক্ত।

isInputPending() ব্যবহার করবেন না

Browser Support

  • ক্রোম: ৮৭।
  • প্রান্ত: ৮৭।
  • ফায়ারফক্স: সমর্থিত নয়।
  • সাফারি: সমর্থিত নয়।

Source

isInputPending() API একটি ব্যবহারকারী কোনও পৃষ্ঠার সাথে ইন্টারঅ্যাক্ট করার চেষ্টা করেছে কিনা তা পরীক্ষা করার একটি উপায় প্রদান করে এবং যদি কোনও ইনপুট মুলতুবি থাকে তবেই তা প্রদান করে।

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

তবে, সেই API চালু হওয়ার পর থেকে, বিশেষ করে INP প্রবর্তনের সাথে সাথে, yielding সম্পর্কে আমাদের ধারণা বৃদ্ধি পেয়েছে। আমরা আর এই API ব্যবহার করার পরামর্শ দিচ্ছি না , বরং বিভিন্ন কারণে ইনপুট পেন্ডিং আছে কিনা তা নির্বিশেষে yielding করার পরামর্শ দিচ্ছি:

  • isInputPending() ব্যবহারকারী কিছু পরিস্থিতিতে ইন্টারঅ্যাক্ট করলেও ভুলভাবে false ফেরত দিতে পারে।
  • ইনপুটই একমাত্র ক্ষেত্রে নয় যেখানে কাজগুলি ফলপ্রসূ হওয়া উচিত। অ্যানিমেশন এবং অন্যান্য নিয়মিত ইউজার ইন্টারফেস আপডেটগুলি একটি প্রতিক্রিয়াশীল ওয়েব পৃষ্ঠা প্রদানের জন্য সমানভাবে গুরুত্বপূর্ণ হতে পারে।
  • এরপর থেকে আরও ব্যাপক ফলনশীল API চালু করা হয়েছে যা ফলনশীল সমস্যাগুলি সমাধান করে, যেমন scheduler.postTask() এবং scheduler.yield()

উপসংহার

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

  • গুরুত্বপূর্ণ, ব্যবহারকারী-মুখী কাজের জন্য মূল থ্রেড ব্যবহার করুন।
  • scheduler.yield() ব্যবহার করে (ক্রস-ব্রাউজার ফলব্যাক সহ) এরগনোমিকভাবে ফলন পেতে এবং অগ্রাধিকারপ্রাপ্ত ধারাবাহিকতা পেতে
  • পরিশেষে, আপনার কাজে যতটা সম্ভব কম কাজ করুন।

scheduler.yield() , এর স্পষ্ট টাস্ক-শিডিউলিং সম্পর্কিত scheduler.postTask() এবং টাস্ক অগ্রাধিকার সম্পর্কে আরও জানতে, Prioritized Task Scheduling API ডক্স দেখুন।

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

এই নির্দেশিকাটির প্রযুক্তিগত যাচাই-বাছাইয়ের জন্য ফিলিপ ওয়ালটনকে বিশেষ ধন্যবাদ।

থাম্বনেইল ছবিটি আনস্প্ল্যাশ থেকে সংগৃহীত, সৌজন্যে আমিরালি মিরহাশেমিয়ান