Scheduler.yield অরিজিন ট্রায়াল উপস্থাপন করা হচ্ছে

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

ওয়েব ডেভেলপারদের তাদের ওয়েবসাইটগুলিকে যতটা সহজ করতে পারে ততটা চটপটে করতে সাহায্য করে এমন নতুন API সরবরাহ করার অব্যাহত প্রচেষ্টায়, Chrome টিম বর্তমানে Chrome-এর 115 সংস্করণ থেকে শুরু করে scheduler.yield এর জন্য একটি অরিজিন ট্রায়াল চালাচ্ছে৷ scheduler.yield হল শিডিউলার এপিআই-তে একটি প্রস্তাবিত নতুন সংযোজন যা ঐতিহ্যগতভাবে যে পদ্ধতিগুলির উপর নির্ভর করা হয়েছে তার চেয়ে মূল থ্রেডে নিয়ন্ত্রণ ফিরিয়ে আনার সহজ এবং ভাল উপায় উভয়েরই অনুমতি দেয়।

ফলন উপর

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

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

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

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

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

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

বর্তমান ফলন কৌশল সঙ্গে সমস্যা

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

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

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

  1. পর্যায়ক্রমে কাজ চালান লেবেলযুক্ত শীর্ষ বোতামটি ক্লিক করুন, যা প্রতিবার চালানোর জন্য ব্লকিং কাজগুলি নির্ধারণ করবে। যখন আপনি এই বোতামটি ক্লিক করেন, টাস্ক লগটি setInterval সাথে Ran ব্লকিং টাস্ক পড়া বেশ কয়েকটি বার্তার সাথে পপুলেট হবে।
  2. এর পরে, রান লুপ লেবেলযুক্ত বোতামটি ক্লিক করুন, প্রতিটি পুনরাবৃত্তিতে setTimeout সহ ফলন

আপনি লক্ষ্য করবেন যে ডেমোর নীচের বাক্সটি এরকম কিছু পড়বে:

Processing loop item 1
Processing loop item 2
Ran blocking task via setInterval
Processing loop item 3
Ran blocking task via setInterval
Processing loop item 4
Ran blocking task via setInterval
Processing loop item 5
Ran blocking task via setInterval
Ran blocking task via setInterval

এই আউটপুট "টাস্ক সারির শেষ" আচরণ প্রদর্শন করে যা setTimeout এর সাথে ফলন করার সময় ঘটে। যে লুপটি চালায় তা পাঁচটি আইটেম প্রক্রিয়া করে এবং প্রতিটি প্রক্রিয়া করার পরে setTimeout সাথে ফল দেয়।

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

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

scheduler.yield লিখুন

Chrome-এর সংস্করণ 115 থেকে scheduler.yield একটি পরীক্ষামূলক ওয়েব প্ল্যাটফর্ম বৈশিষ্ট্য হিসাবে একটি পতাকার পিছনে উপলব্ধ। আপনার একটি প্রশ্ন হতে পারে "যখন setTimeout ইতিমধ্যেই এটি করে তখন কেন আমার ফলন করার জন্য একটি বিশেষ ফাংশন দরকার?"

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

scheduler.yield হল একটি ফাংশন যা মূল থ্রেডে প্রাপ্ত হয় এবং কল করার সময় একটি Promise প্রদান করে। এর মানে আপনি একটি async ফাংশনে এটির await করতে পারেন:

async function yieldy () {
  // Do some work...
  // ...

  // Yield!
  await scheduler.yield();

  // Do some more work...
  // ...
}

ক্রিয়াশীল scheduler.yield দেখতে, নিম্নলিখিতগুলি করুন:

  1. chrome://flags এ নেভিগেট করুন।
  2. পরীক্ষামূলক ওয়েব প্ল্যাটফর্ম বৈশিষ্ট্য পরীক্ষা সক্ষম করুন৷ এটি করার পরে আপনাকে Chrome পুনরায় চালু করতে হতে পারে।
  3. ডেমো পৃষ্ঠাতে নেভিগেট করুন বা এই তালিকার নীচে এটির এমবেডেড সংস্করণ ব্যবহার করুন৷
  4. পর্যায়ক্রমে কাজ চালান লেবেলযুক্ত উপরের বোতামে ক্লিক করুন।
  5. অবশেষে, রান লুপ লেবেলযুক্ত বোতামটি ক্লিক করুন, প্রতিটি পুনরাবৃত্তিতে scheduler.yield সহ ফলন

পৃষ্ঠার নীচের বাক্সে আউটপুটটি এরকম কিছু দেখাবে:

Processing loop item 1
Processing loop item 2
Processing loop item 3
Processing loop item 4
Processing loop item 5
Ran blocking task via setInterval
Ran blocking task via setInterval
Ran blocking task via setInterval
Ran blocking task via setInterval
Ran blocking task via setInterval

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

একবার চেষ্টা করে দেখো!

যদি scheduler.yield আপনার কাছে আকর্ষণীয় মনে হয় এবং আপনি এটি ব্যবহার করে দেখতে চান, তাহলে আপনি Chrome এর 115 সংস্করণ থেকে শুরু করে দুটি উপায়ে তা করতে পারেন:

  1. আপনি স্থানীয়ভাবে scheduler.yield নিয়ে পরীক্ষা করতে চাইলে, টাইপ করুন এবং ক্রোমের ঠিকানা বারে chrome://flags লিখুন এবং পরীক্ষামূলক ওয়েব প্ল্যাটফর্ম বৈশিষ্ট্য বিভাগে ড্রপডাউন থেকে সক্ষম নির্বাচন করুন। এটি কেবলমাত্র আপনার Chrome-এর উদাহরণে scheduler.yield (এবং অন্য কোনো পরীক্ষামূলক বৈশিষ্ট্য) উপলব্ধ করবে।
  2. আপনি যদি সার্বজনীনভাবে অ্যাক্সেসযোগ্য মূলে প্রকৃত Chromium ব্যবহারকারীদের জন্য scheduler.yield সক্ষম করতে চান, তাহলে আপনাকে scheduler.yield অরিজিন ট্রায়ালের জন্য সাইন আপ করতে হবে। এটি আপনাকে একটি নির্দিষ্ট সময়ের জন্য প্রস্তাবিত বৈশিষ্ট্যগুলির সাথে নিরাপদে পরীক্ষা করার অনুমতি দেয় এবং সেই বৈশিষ্ট্যগুলি কীভাবে ক্ষেত্রে ব্যবহার করা হয় সে সম্পর্কে Chrome টিমকে মূল্যবান অন্তর্দৃষ্টি দেয়৷ মূল পরীক্ষাগুলি কীভাবে কাজ করে সে সম্পর্কে আরও তথ্যের জন্য, এই নির্দেশিকাটি পড়ুন

আপনি কিভাবে scheduler.yield ব্যবহার করেন—যদিও ব্রাউজারগুলিকে সমর্থন করে যেগুলি এটি বাস্তবায়ন করে না—আপনার লক্ষ্যগুলি কী তার উপর নির্ভর করে। আপনি অফিসিয়াল পলিফিল ব্যবহার করতে পারেন। পলিফিল দরকারী যদি নিম্নলিখিতগুলি আপনার পরিস্থিতিতে প্রযোজ্য হয়:

  1. আপনি ইতিমধ্যেই আপনার অ্যাপ্লিকেশনে scheduler.postTask ব্যবহার করছেন টাস্ক শিডিউল করতে।
  2. আপনি কাজ এবং ফলন অগ্রাধিকার সেট করতে সক্ষম হতে চান.
  3. আপনি TaskController ক্লাসের মাধ্যমে কাজগুলি বাতিল করতে বা পুনঃপ্রাথমিক করতে সক্ষম হতে চান scheduler.postTask API অফার করে।

যদি এটি আপনার পরিস্থিতি বর্ণনা না করে, তাহলে পলিফিল আপনার জন্য নাও হতে পারে। সেই ক্ষেত্রে, আপনি কয়েকটি উপায়ে আপনার নিজের ফলব্যাক রোল করতে পারেন। প্রথম পদ্ধতিটি যদি উপলব্ধ থাকে তাহলে scheduler.yield ব্যবহার করে, কিন্তু সেটি না থাকলে setTimeout ফিরে যায়:

// A function for shimming scheduler.yield and setTimeout:
function yieldToMain () {
  // Use scheduler.yield if it exists:
  if ('scheduler' in window && 'yield' in scheduler) {
    return scheduler.yield();
  }

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

// Example usage:
async function doWork () {
  // Do some work:
  // ...

  await yieldToMain();

  // Do some other work:
  // ...
}

এটি কাজ করতে পারে, কিন্তু আপনি অনুমান করতে পারেন, যে ব্রাউজারগুলি scheduler.yield সমর্থন করে না তারা "সারির সামনে" আচরণ ছাড়াই ফল দেবে। যদি এর মানে হল যে আপনি একেবারেই ফলন না করতে চান, আপনি অন্য পদ্ধতির চেষ্টা করতে পারেন যেটি উপলব্ধ থাকলে scheduler.yield ব্যবহার করে, কিন্তু এটি না হলে একেবারেই ফল দেবে না:

// A function for shimming scheduler.yield with no fallback:
function yieldToMain () {
  // Use scheduler.yield if it exists:
  if ('scheduler' in window && 'yield' in scheduler) {
    return scheduler.yield();
  }

  // Fall back to nothing:
  return;
}

// Example usage:
async function doWork () {
  // Do some work:
  // ...

  await yieldToMain();

  // Do some other work:
  // ...
}

scheduler.yield হল শিডিউলার এপিআই-তে একটি উত্তেজনাপূর্ণ সংযোজন- যা আশা করি ডেভেলপারদের জন্য বর্তমান ফলন কৌশলগুলির তুলনায় প্রতিক্রিয়াশীলতা উন্নত করা সহজ করে তুলবে। যদি scheduler.yield আপনার কাছে একটি দরকারী API বলে মনে হয়, তাহলে অনুগ্রহ করে এটিকে উন্নত করতে সাহায্য করতে আমাদের গবেষণায় অংশগ্রহণ করুন এবং এটিকে কীভাবে আরও উন্নত করা যেতে পারে সে সম্পর্কে মতামত দিন

জোনাথন অ্যালিসন দ্বারা আনস্প্ল্যাশ থেকে হিরো চিত্র।