আপনার জাভাস্ক্রিপ্ট অ্যাপ্লিকেশানগুলিকে দ্রুততর করার জন্য সাধারণভাবে উপলভ্য পরামর্শের মধ্যে প্রায়ই "প্রধান থ্রেড ব্লক করবেন না" এবং "আপনার দীর্ঘ কাজগুলি ভেঙে দিন" অন্তর্ভুক্ত থাকে। এই পৃষ্ঠাটি সেই পরামর্শের অর্থ কী এবং কেন জাভাস্ক্রিপ্টে কাজগুলি অপ্টিমাইজ করা গুরুত্বপূর্ণ তা ভেঙে দেয়।
একটি টাস্ক কি?
একটি টাস্ক হল ব্রাউজার যে কোন আলাদা কাজ করে। এর মধ্যে রয়েছে রেন্ডারিং, HTML এবং CSS পার্স করা, আপনার লেখা জাভাস্ক্রিপ্ট কোড চালানো এবং অন্যান্য জিনিসের উপর আপনার সরাসরি নিয়ন্ত্রণ নাও থাকতে পারে। আপনার পৃষ্ঠাগুলির জাভাস্ক্রিপ্ট ব্রাউজারের কাজের একটি প্রধান উৎস।
টাস্ক বিভিন্ন উপায়ে কর্মক্ষমতা প্রভাবিত করে। উদাহরণস্বরূপ, যখন একটি ব্রাউজার স্টার্টআপের সময় একটি জাভাস্ক্রিপ্ট ফাইল ডাউনলোড করে, তখন এটি সেই জাভাস্ক্রিপ্ট পার্স এবং কম্পাইল করার জন্য কাজগুলিকে সারিবদ্ধ করে যাতে এটি কার্যকর করা যায়। পরবর্তীতে পৃষ্ঠার জীবনচক্রে, অন্যান্য কাজগুলি শুরু হয় যখন আপনার জাভাস্ক্রিপ্ট কাজ করে যেমন ইভেন্ট হ্যান্ডলারের মাধ্যমে ড্রাইভিং মিথস্ক্রিয়া, জাভাস্ক্রিপ্ট-চালিত অ্যানিমেশন এবং ব্যাকগ্রাউন্ড কার্যকলাপ যেমন বিশ্লেষণ সংগ্রহ। এই সব, ওয়েব কর্মী এবং অনুরূপ API ব্যতীত, প্রধান থ্রেডে ঘটে।
মূল থ্রেড কি?
প্রধান থ্রেড হল যেখানে বেশিরভাগ কাজ ব্রাউজারে চলে এবং যেখানে আপনার লেখা প্রায় সমস্ত জাভাস্ক্রিপ্ট চালানো হয়।
প্রধান থ্রেড একটি সময়ে শুধুমাত্র একটি কাজ প্রক্রিয়া করতে পারে. যে কোনো কাজ যা 50 মিলিসেকেন্ডের বেশি সময় নেয় তা একটি দীর্ঘ কাজ হিসাবে গণনা করা হয়। যদি ব্যবহারকারী একটি দীর্ঘ টাস্ক বা একটি রেন্ডারিং আপডেটের সময় পৃষ্ঠাটির সাথে ইন্টারঅ্যাক্ট করার চেষ্টা করে, তবে ব্রাউজারটিকে অবশ্যই সেই ইন্টারঅ্যাকশনটি পরিচালনা করার জন্য অপেক্ষা করতে হবে, যার ফলে বিলম্ব হয়।
এটি প্রতিরোধ করার জন্য, প্রতিটি দীর্ঘ টাস্ককে ছোট ছোট কাজগুলিতে ভাগ করুন যা প্রতিটি চালাতে কম সময় নেয়। একে বলে ব্রেকিং আপ লং টাস্ক।
ব্রেকিং টাস্ক আপ ব্রাউজারকে অন্যান্য কাজের মধ্যে ব্যবহারকারীর মিথস্ক্রিয়া সহ উচ্চ-অগ্রাধিকারমূলক কাজে সাড়া দেওয়ার আরও সুযোগ দেয়। এটি মিথস্ক্রিয়াগুলিকে আরও দ্রুত ঘটতে দেয়, যেখানে ব্রাউজারটি দীর্ঘ কাজ শেষ করার জন্য অপেক্ষা করার সময় একজন ব্যবহারকারী অন্যথায় ল্যাগ লক্ষ্য করতে পারে।
টাস্ক ম্যানেজমেন্ট কৌশল
জাভাস্ক্রিপ্ট প্রতিটি ফাংশনকে একটি একক কাজ হিসাবে বিবেচনা করে, কারণ এটি কার্য সম্পাদনের একটি রান-টু-সম্পূর্ণ মডেল ব্যবহার করে। এর মানে হল যে একটি ফাংশন যা একাধিক অন্যান্য ফাংশনকে কল করে, নিম্নলিখিত উদাহরণের মতো, সমস্ত কথিত ফাংশন সম্পূর্ণ না হওয়া পর্যন্ত চলতে হবে, যা ব্রাউজারকে ধীর করে দেয়:
function saveSettings () { //This is a long task.
validateForm();
showSpinner();
saveToDatabase();
updateUI();
sendAnalytics();
}
যদি আপনার কোডে এমন ফাংশন থাকে যা একাধিক পদ্ধতি কল করে, তবে এটিকে একাধিক ফাংশনে বিভক্ত করুন। এটি শুধুমাত্র ব্রাউজারকে ইন্টারঅ্যাকশনে সাড়া দেওয়ার আরও সুযোগ দেয় না, তবে এটি আপনার কোড পড়া, রক্ষণাবেক্ষণ এবং পরীক্ষা লিখতে সহজ করে তোলে। নিম্নলিখিত বিভাগগুলি দীর্ঘ ফাংশনগুলিকে ভেঙে ফেলার এবং সেগুলিকে তৈরি করে এমন কাজগুলিকে অগ্রাধিকার দেওয়ার জন্য কিছু কৌশল নিয়ে চলে।
ম্যানুয়ালি কোড এক্সিকিউশন পিছিয়ে দিন
আপনি প্রাসঙ্গিক ফাংশন 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);
}
এটি ফাংশনগুলির একটি সিরিজের জন্য সবচেয়ে ভাল কাজ করে যা ক্রমানুসারে চালানো প্রয়োজন। ভিন্নভাবে সংগঠিত কোডের জন্য ভিন্ন পদ্ধতির প্রয়োজন। পরবর্তী উদাহরণ হল একটি ফাংশন যা একটি লুপ ব্যবহার করে প্রচুর পরিমাণে ডেটা প্রক্রিয়া করে। ডেটাসেটটি যত বড় হবে, তত বেশি সময় লাগবে এবং setTimeout()
রাখার জন্য লুপে একটি ভাল জায়গা থাকা আবশ্যক নয় :
function processData () {
for (const item of largeDataArray) {
// Process the individual item here.
}
}
সৌভাগ্যবশত, আরও কয়েকটি এপিআই রয়েছে যা আপনাকে পরবর্তী কাজের জন্য কোড এক্সিকিউশন স্থগিত করতে দেয়। আমরা দ্রুত সময়ের জন্য postMessage()
ব্যবহার করার পরামর্শ দিই।
আপনি requestIdleCallback()
ব্যবহার করেও কাজ ভাঙতে পারেন, কিন্তু এটি সর্বনিম্ন অগ্রাধিকারে এবং শুধুমাত্র ব্রাউজার নিষ্ক্রিয় সময়ের মধ্যে কাজগুলির সময়সূচী নির্ধারণ করে, যার অর্থ যদি প্রধান থ্রেডটি বিশেষভাবে ব্যস্ত থাকে, requestIdleCallback()
এর সাথে নির্ধারিত কাজগুলি কখনই চলতে পারে না।
ফলন পয়েন্ট তৈরি করতে async
/ await
ব্যবহার করুন
নিম্ন-অগ্রাধিকারমূলক কাজগুলির আগে গুরুত্বপূর্ণ ব্যবহারকারী-মুখী কাজগুলি নিশ্চিত করতে, ব্রাউজারকে আরও গুরুত্বপূর্ণ কাজগুলি চালানোর সুযোগ দেওয়ার জন্য টাস্ক কিউতে সংক্ষিপ্তভাবে বাধা দিয়ে মূল থ্রেডে উঠুন ।
এটি করার সবচেয়ে পরিষ্কার উপায়ে একটি Promise
জড়িত যা setTimeout()
এ কল দিয়ে সমাধান করে:
function yieldToMain () {
return new Promise(resolve => {
setTimeout(resolve, 0);
});
}
saveSettings()
ফাংশনে, আপনি প্রতিটি ধাপের পরে মূল থ্রেডে উঠতে পারেন যদি আপনি প্রতিটি ফাংশন কলের পরে yieldToMain()
ফাংশনের await
। এটি কার্যকরভাবে আপনার দীর্ঘ টাস্ককে একাধিক টাস্কে বিভক্ত করে:
async function saveSettings () {
// Create an array of functions to run:
const tasks = [
validateForm,
showSpinner,
saveToDatabase,
updateUI,
sendAnalytics
]
// Loop over the tasks:
while (tasks.length > 0) {
// Shift the first task off the tasks array:
const task = tasks.shift();
// Run the task:
task();
// Yield to the main thread:
await yieldToMain();
}
}
মূল পয়েন্ট: প্রতিটি ফাংশন কলের পরে আপনাকে ফল দিতে হবে না। উদাহরণস্বরূপ, আপনি যদি দুটি ফাংশন চালান যার ফলে ব্যবহারকারী ইন্টারফেসে সমালোচনামূলক আপডেট হয়, আপনি সম্ভবত তাদের মধ্যে ফলন করতে চান না। যদি আপনি পারেন, সেই কাজটিকে প্রথমে চলতে দিন, তারপরে ব্যাকগ্রাউন্ড বা কম সমালোচনামূলক কাজ যা ব্যবহারকারী দেখতে পান না এমন ফাংশনগুলির মধ্যে ফলন বিবেচনা করুন৷
একটি ডেডিকেটেড সময়সূচী API
এ পর্যন্ত উল্লিখিত API গুলি আপনাকে কাজগুলি ভেঙে ফেলতে সাহায্য করতে পারে, তবে তাদের একটি উল্লেখযোগ্য নেতিবাচক দিক রয়েছে: আপনি যখন পরবর্তী টাস্কে চালানোর জন্য কোডটি স্থগিত করে মূল থ্রেডে যোগদান করেন, তখন সেই কোডটি টাস্ক সারির শেষে যোগ করা হয়।
আপনি যদি আপনার পৃষ্ঠার সমস্ত কোড নিয়ন্ত্রণ করেন, আপনি কাজগুলিকে অগ্রাধিকার দিতে আপনার নিজস্ব সময়সূচী তৈরি করতে পারেন৷ যাইহোক, তৃতীয় পক্ষের স্ক্রিপ্টগুলি আপনার সময়সূচী ব্যবহার করবে না, তাই আপনি সেই ক্ষেত্রে কাজকে সত্যিই অগ্রাধিকার দিতে পারবেন না। আপনি কেবল এটিকে ভেঙে ফেলতে পারেন বা ব্যবহারকারীর ইন্টারঅ্যাকশনে যোগ দিতে পারেন।
শিডিউলার এপিআই postTask()
ফাংশন অফার করে, যা কাজের সূক্ষ্ম সময়সূচীর জন্য অনুমতি দেয় এবং ব্রাউজারকে কাজকে অগ্রাধিকার দিতে সাহায্য করতে পারে যাতে কম অগ্রাধিকারের কাজগুলি মূল থ্রেডে আসে। postTask()
প্রতিশ্রুতি ব্যবহার করে এবং একটি priority
সেটিং গ্রহণ করে।
postTask()
API-এর তিনটি অগ্রাধিকার উপলব্ধ রয়েছে:
- সর্বনিম্ন অগ্রাধিকারমূলক কাজের জন্য
'background'
। - মাঝারি অগ্রাধিকারমূলক কাজের জন্য
'user-visible'
। কোনpriority
সেট না থাকলে এটি ডিফল্ট। -
'user-blocking'
গুরুত্বপূর্ণ কাজগুলির জন্য যা উচ্চ অগ্রাধিকারে চালানো প্রয়োজন।
নিম্নলিখিত উদাহরণ কোডটি সর্বোচ্চ সম্ভাব্য অগ্রাধিকারে তিনটি কাজ চালানোর জন্য postTask()
API ব্যবহার করে, এবং বাকি দুটি কাজ সর্বনিম্ন সম্ভাব্য অগ্রাধিকারে:
function saveSettings () {
// Validate the form at high priority
scheduler.postTask(validateForm, {priority: 'user-blocking'});
// Show the spinner at high priority:
scheduler.postTask(showSpinner, {priority: 'user-blocking'});
// Update the database in the background:
scheduler.postTask(saveToDatabase, {priority: 'background'});
// Update the user interface at high priority:
scheduler.postTask(updateUI, {priority: 'user-blocking'});
// Send analytics data in the background:
scheduler.postTask(sendAnalytics, {priority: 'background'});
};
এখানে, কাজের অগ্রাধিকার নির্ধারিত হয়েছে যাতে ব্যবহারকারীর ইন্টারঅ্যাকশনের মতো ব্রাউজার-অগ্রাধিকারযুক্ত কাজগুলি তাদের পথে কাজ করতে পারে।
এছাড়াও আপনি বিভিন্ন TaskController
অবজেক্টকে ইনস্ট্যান্টিয়েট করতে পারেন যা প্রয়োজন অনুযায়ী বিভিন্ন TaskController
ইনস্ট্যান্সের জন্য অগ্রাধিকার পরিবর্তন করার ক্ষমতা সহ কাজের মধ্যে অগ্রাধিকার ভাগ করে।
আসন্ন scheduler.yield()
API ব্যবহার করে ধারাবাহিকতা সহ অন্তর্নির্মিত ফলন
মূল পয়েন্ট: scheduler.yield()
এর আরও বিশদ ব্যাখ্যার জন্য, এর মূল ট্রায়াল সম্পর্কে পড়ুন (যেহেতু শেষ হয়েছে), সেইসাথে এর ব্যাখ্যাকারীও ।
শিডিউলার এপিআই-তে একটি প্রস্তাবিত সংযোজন হল scheduler.yield()
, একটি এপিআই যা ব্রাউজারে প্রধান থ্রেডের জন্য বিশেষভাবে ডিজাইন করা হয়েছে। এর ব্যবহার এই পৃষ্ঠায় আগে প্রদর্শিত yieldToMain()
ফাংশনের অনুরূপ:
async function saveSettings () {
// Create an array of functions to run:
const tasks = [
validateForm,
showSpinner,
saveToDatabase,
updateUI,
sendAnalytics
]
// Loop over the tasks:
while (tasks.length > 0) {
// Shift the first task off the tasks array:
const task = tasks.shift();
// Run the task:
task();
// Yield to the main thread with the scheduler
// API's own yielding mechanism:
await scheduler.yield();
}
}
এই কোডটি মূলত পরিচিত, কিন্তু yieldToMain()
ব্যবহার করার পরিবর্তে, এটি await scheduler.yield()
ব্যবহার করে।
scheduler.yield()
এর সুবিধা হল ধারাবাহিকতা, যার মানে হল যে আপনি যদি একটি সেট কাজের মাঝখানে ফলন করেন, তবে অন্যান্য নির্ধারিত কাজগুলি ফলন পয়েন্টের পরে একই ক্রমে চলতে থাকে। এটি তৃতীয় পক্ষের স্ক্রিপ্টগুলিকে আপনার কোড যে ক্রমটি সম্পাদন করে তার নিয়ন্ত্রণ নিতে বাধা দেয়৷
scheduler.postTask()
priority: 'user-blocking'
এরও উচ্চ user-blocking
অগ্রাধিকারের কারণে অব্যাহত থাকার একটি উচ্চ সম্ভাবনা রয়েছে, তাই আপনি এটিকে বিকল্প হিসাবে ব্যবহার করতে পারেন যতক্ষণ না scheduler.yield()
আরও ব্যাপকভাবে উপলব্ধ হয়।
অগ্রাধিকার সহ setTimeout()
(বা scheduler.postTask()
ব্যবহার করে priority: 'user-visible'
বা কোন স্পষ্ট priority
নেই
isInputPending()
সহ ইনপুটে ফলন
ব্রাউজার সমর্থন
- 87
- 87
- এক্স
- এক্স
isInputPending()
API একজন ব্যবহারকারী একটি পৃষ্ঠার সাথে ইন্টারঅ্যাক্ট করার চেষ্টা করেছে কিনা তা পরীক্ষা করার একটি উপায় প্রদান করে এবং শুধুমাত্র একটি ইনপুট মুলতুবি থাকলেই ফল দেয়।
এটি জাভাস্ক্রিপ্টকে চালিয়ে যেতে দেয় যদি কোনও ইনপুট মুলতুবি না থাকে, ফলন না করে এবং টাস্ক কিউয়ের পিছনে শেষ হয়। এর ফলে প্রভাবশালী পারফরম্যান্সের উন্নতি হতে পারে, যেমনটি Intent to Ship- এ বিশদভাবে বলা হয়েছে, এমন সাইটগুলির জন্য যা অন্যথায় মূল থ্রেডে ফিরে আসতে পারে না।
যাইহোক, সেই API চালু হওয়ার পর থেকে, ফলন সম্পর্কে আমাদের বোঝার উন্নতি হয়েছে, বিশেষ করে INP প্রবর্তনের পরে। আমরা আর এই API ব্যবহার করার সুপারিশ করি না , এবং পরিবর্তে ইনপুট মুলতুবি থাকুক বা না থাকুক না কেন ফলন দেওয়ার সুপারিশ করি। সুপারিশের এই পরিবর্তনটি বেশ কয়েকটি কারণে হয়েছে:
- API ভুলভাবে কিছু ক্ষেত্রে
false
ফেরত দিতে পারে যেখানে একজন ব্যবহারকারী ইন্টারঅ্যাক্ট করেছে। - ইনপুট একমাত্র ক্ষেত্রে নয় যেখানে কার্যগুলি পাওয়া উচিত। অ্যানিমেশন এবং অন্যান্য নিয়মিত ব্যবহারকারী ইন্টারফেস আপডেট একটি প্রতিক্রিয়াশীল ওয়েব পৃষ্ঠা প্রদানের জন্য সমানভাবে গুরুত্বপূর্ণ হতে পারে।
-
scheduler.postTask()
এবংscheduler.yield()
এর মতো আরও ব্যাপক ফলনকারী APIগুলি ফলন সংক্রান্ত উদ্বেগগুলিকে সমাধান করার জন্য চালু করা হয়েছে৷
উপসংহার
কাজগুলি পরিচালনা করা চ্যালেঞ্জিং, কিন্তু এটি করা আপনার পৃষ্ঠাকে ব্যবহারকারীর ইন্টারঅ্যাকশনে আরও দ্রুত প্রতিক্রিয়া জানাতে সহায়তা করে। আপনার ব্যবহারের ক্ষেত্রে নির্ভর করে কাজগুলি পরিচালনা এবং অগ্রাধিকার দেওয়ার জন্য বিভিন্ন কৌশল রয়েছে। পুনরাবৃত্ত করার জন্য, এইগুলি হল প্রধান জিনিসগুলি যা আপনি কাজগুলি পরিচালনা করার সময় বিবেচনা করতে চান:
- গুরুত্বপূর্ণ, ব্যবহারকারী-মুখী কাজগুলির জন্য মূল থ্রেডে যোগ দিন।
-
scheduler.yield()
নিয়ে পরীক্ষা করার কথা বিবেচনা করুন। -
postTask()
দিয়ে কাজগুলোকে অগ্রাধিকার দিন। - অবশেষে, আপনার ফাংশনে যতটা সম্ভব কম কাজ করুন।
এই সরঞ্জামগুলির মধ্যে এক বা একাধিক দিয়ে, আপনি আপনার অ্যাপ্লিকেশনে কাজটি গঠন করতে সক্ষম হবেন যাতে এটি ব্যবহারকারীর চাহিদাগুলিকে অগ্রাধিকার দেয় এবং নিশ্চিত করে যে কম সমালোচনামূলক কাজ এখনও সম্পন্ন হয়। এটি ব্যবহারকারীর অভিজ্ঞতাকে আরও প্রতিক্রিয়াশীল এবং ব্যবহারে আরও উপভোগ্য করে উন্নত করে৷
ফিলিপ ওয়ালটনকে বিশেষ ধন্যবাদ তার এই নথির প্রযুক্তিগত পরীক্ষা করার জন্য।
থাম্বনেইল ছবি আনস্প্ল্যাশ থেকে নেওয়া, আমিরালি মিরহাশেমিয়ানের সৌজন্যে।