প্রবর্তন আধুনিক ওয়েব অ্যাপ্লিকেশনগুলি ভারী হতে পারে. কখনও কখনও, দীর্ঘ সময় ধরে চলমান একক JavaScript ফাংশন ইন্টারফেসটি ফ্রিজ করার জন্য যথেষ্ট, ব্যবহারকারীদের হতাশ করে এবং অবিশ্বাস করে যে অ্যাপ্লিকেশনটি এখনও কাজ করছে কিনা বা ফ্রিজ হয়েছে কিনা। একটি ছোট কিন্তু শক্তিশালী পদ্ধতি প্রবর্তন করে: এটি একটি ব্যবহারকারীকে কার্যক্রম স্থগিত করার অনুমতি দেয়, ব্রাউজারকে আরও গুরুত্বপূর্ণ কাজগুলি (যেমন ক্লিক বা টাইপিং) পরিচালনা করার সুযোগ দেয়, এবং তারপর ঠিক সেখানে অব্যাহত থাকবে। , পুরাতন workarounds অনুসন্ধান করুন, এবং দেখুন কিভাবে জীবনকে সহজ করে তোলে। অ্যাপ্লিকেশন অ্যাপ্লিকেশন API অ্যাপ্লিকেশন ( Main Thread scheduler.yield() তাহলে তাহলে কি সঠিক? সুতরাং, কী এটি একটি পদ্ধতি যা নতুন থেকে ইন্টারফেস এই পদ্ধতিটি আপনাকে একটি ডেভেলপার হিসাবে আপনাকে আপনার জ্যোতিষ্ক্রিপ্ট বাস্তবায়ন স্থগিত করতে এবং স্পষ্টভাবে নিয়ন্ত্রণ ফিরিয়ে আনতে দেয়। – তাই এটি অন্যান্য অপেক্ষাকৃত গুরুত্বপূর্ণ কাজগুলি, যেমন ব্যবহারকারীর ইন্টারেক্টিভেশন, ক্লিক, টাইপিং, ইত্যাদি, পরিচালনা করতে পারে এবং তারপর আপনি যেখান থেকে চালানোর শুরু করতে পারেন। আপনি ব্রাউজারকে বলছেন: scheduler.yield() পরিকল্পনা অ্যাপ্লিকেশন অ্যাপ্লিকেশন API Main Thread scheduler.yield() "আপনি অপেক্ষা করুন, একটি নিঃশ্বাস নিন, চলুন বর্তমান কাজটি স্থগিত করুন এবং অন্য কোনও কম বা বেশি গুরুত্বপূর্ণ কাজের উপর ফোকাস করুন। "আপনি অপেক্ষা করুন, একটি নিঃশ্বাস নিন, চলুন বর্তমান কাজটি স্থগিত করুন এবং অন্য কোনও কম বা বেশি গুরুত্বপূর্ণ কাজের উপর ফোকাস করুন। এটি আপনার পৃষ্ঠাটি আরও প্রতিক্রিয়াশীল করে তোলে, বিশেষ করে দীর্ঘ বা ভারী জাভাস্ক্রিপ্ট কাজ চালানোর সময়। – যা সব ব্রাউজার ব্যবহারকারীর ইনপুট প্রতিক্রিয়া কত দ্রুত উপর নির্ভর করে। Next Paint (INP) এর সাথে ইন্টারেকশন টার্মিনাল আপনি আরও গভীরভাবে ডুবে যাওয়ার আগে, আমরা দ্রুত কিছু মৌলিক শব্দগুলির উপর যাব যা পুরো নিবন্ধটিতে ব্যবহৃত হবে। প্রধান থ্রেড - এটি কেন্দ্রীয় জায়গা যেখানে ব্রাউজার তার বেশিরভাগ কাজ করে. এটি রেন্ডারিং, লেআউট পরিচালনা করে, এবং আপনার JavaScript কোডের বেশিরভাগটি চালু করে। দীর্ঘ কাজ - এটি যেকোনো জাভাস্ক্রিপ্ট কাজ যা প্রধান থ্রেডটি খুব দীর্ঘ সময় ধরে ব্যস্ত রাখে, সাধারণত 50 মিলিসেকেন্ডের বেশি। ব্লকিং টাস্ক - মাইক্রো থ্রেডে একটি সমন্বিত অপারেশন যা ব্রাউজারকে অন্যান্য গুরুত্বপূর্ণ জিনিসগুলি প্রক্রিয়াকরণ করতে বাধা দেয়, যেমন ক্লিকগুলি প্রতিক্রিয়া বা ইউআই আপডেট করা। সমস্যা সৌন্দর্য বুঝার জন্য , আপনাকে প্রথমে বুঝতে হবে যে কোন সমস্যাটি সমাধান করার চেষ্টা করছে. জাভাস্ক্রিপ্ট একক থ্রেডে চালানো হয়. এর মানে হল এটি একবারে শুধুমাত্র একটি জিনিস করতে পারে. যদি আপনার কোডটি থ্রেডটি ব্যস্ত রাখে, তাহলে বাকি সবকিছু – রেন্ডিং, বোতাম ক্লিক, ইনপুটিং অপেক্ষা করতে হবে। scheduler.yield() JavaScript Execution মডেল একটি দ্রুত আপলোড হিসাবে, এখানে JavaScript কিভাবে কাজ প্রক্রিয়াকরণ করে তা একটি উদাহরণ চার্ট - অন্য কথায়, কিভাবে আমি নিশ্চিত যে আপনারা অনেকে এই ধরনের চার্টগুলি আগে দেখেছেন - কাজের চার্জ, ইভেন্ট লুক, কল স্ট্যাক. এই একটি নিখুঁত নয়, কিন্তু এটি আপনাকে বড় ছবি দেয়। JavaScript Execution Model আসুন ধাপে ধাপে প্রধান ধারণাগুলির মাধ্যমে হাঁটাহাঁটি করি: সমস্ত সামঞ্জস্যপূর্ণ কোড সরাসরি কল স্ট্যাকে যায় এবং লাইন দ্বারা লাইন, ফাংশন দ্বারা ফাংশন চালানো হয়. এটি LIFO নীতি অনুসরণ করে - শেষ ইন, প্রথম বাইরে. JavaScript একটি একক থ্রেডে চালানো হয়, যার মানে এটি একবারে শুধুমাত্র একটি জিনিস করতে পারে। Asynchronous অপারেশনগুলি (যেমন setTimeout, fetch) প্রধান থ্রেডের বাইরে পরিচালিত হয় - ওয়েব এপিআই (ব্রাউজার বা পরিবেশ দ্বারা সরবরাহ করা হয়)। একবার তারা সম্পন্ন হয়, তারা সরাসরি কল স্ট্যাকে ফিরে যায় না। যখন কল স্ট্যাক খালি হয়, ইভেন্ট লুপটি মাইক্রো-টাস্কের র ্যাংক চেক করে এবং সব মাইক্রো-টাস্কগুলি একের পর এক চালু করে। শুধুমাত্র তারপর, এটি র ্যাংক থেকে একটি ম্যাক্রো টাস্ক নেয় এবং এটি চালু করে। যদি প্রক্রিয়ার সময় নতুন মাইক্রো-টাস্ক যোগ করা হয়, তাহলে তারা পরবর্তী ম্যাক্রো-টাস্কের আগে চালু হয়, তাই মাইক্রো-টাস্ক সবসময় অগ্রাধিকার পায়। এই চক্র চলতে থাকে: সমস্ত মাইক্রো টাস্ক → এক ম্যাক্রো টাস্ক → পুনরাবৃত্তি। নতুন সমন্বিত কোড কল স্ট্যাকে প্রবেশ করে যখন নতুন কাজ আসে, যেমন একটি ব্যবহারকারী একটি বোতাম ক্লিক করে, একটি নতুন স্ক্রিপ্ট চালানো হয়, অথবা যখন একটি মাইক্রোটাস্ক্রিপ্ট বা ম্যাক্রোটাস্ক্রিপ্ট তার কলবোর্ড চালানো হয়। এটি একটি খুব সংক্ষিপ্ত এবং পৃষ্ঠপোষক ব্যাখ্যা, শুধু আপনাকে মনে করিয়ে দেয় যে এটি কীভাবে কাজ করে. কারণ এটি বিষয়টির সাথে আরও ঘনিষ্ঠভাবে মিলিত হবে. সমস্যা বর্ণনা এখন যেহেতু আপনি কিভাবে JavaScript কাজ সম্পাদনা সম্পর্কে আপনার বোঝার আপডেট করেছেন, তাহলে আসুন এই মডেলের সাথে আসা বাস্তব সমস্যার দিকে তাকান। সমস্যাটি সহজ: যখন একটি কাজ প্রধান ট্রেডে খুব দীর্ঘ সময় নেয়, তখন এটি অন্যান্য সবকিছু ব্লক করে – ব্যবহারকারীর ইন্টারেক্টিভেশন, রেন্ডারিং আপডেট এবং অ্যানিমেশন। এটি ইউআই ফ্রিজ এবং খারাপ প্রতিক্রিয়াশীলতার জন্য পরিচালিত করে। তবে আমরা সৎ হতে পারি - "হ্যাঁ, শুধু দীর্ঘ বা ভারী ফাংশন লিখুন না, এবং এটি এটি। সমস্যাটি সমাধান করা হয়েছে" এবং হ্যাঁ, এটি সত্য - একটি আদর্শ বিশ্বে, আপনি সর্বদা কঠোর কোড এর জন্য আমরা একটি ফাংশন তৈরি করব যাকে বলা হয় এই ফাংশন নির্দিষ্ট সময়ের জন্য প্রধান থ্রেডের জন্য একটি ব্লকিং কাজ হিসাবে কাজ করে. ফাংশন মেরের প্রতিটি উপাদান উপর এই ধরনের "বর্ধমান" গণনা সিমুলেশন। blockingTask() দুর্ভাগ্যবশত, কোড ব্লকগুলি লাইন সংখ্যাগুলি প্রদর্শন করে না। দুর্ভাগ্যবশত, কোড ব্লকগুলি লাইন সংখ্যাগুলি প্রদর্শন করে না। function blockingTask(ms = 10) { const arr = []; const start = performance.now(); while (performance.now() - start < ms) { // Perform pointless computation to block the CPU. arr.unshift(Math.sqrt(Math.random())); } return arr; } ফাংশন সম্পর্কে কিছুই চিত্তাকর্ষক নয়, এখানে এটি সবকিছু করে: এটি একটি পরিসংখ্যান গ্রহণ করে - মিলিসেকেন্ডের সংখ্যা. এটি ফাংশনটি চালানোর সর্বনিম্ন সময়, যার ফলে প্রধান থ্রেডটি দখল করে। এটি একটি শূন্য আর্দ্রতা তৈরি করে। এটি একটি শুরু সময় তৈরি করে (একটি বর্তমান সময় হিসাবে)। এরপর নির্দিষ্ট সময়ের জন্য অপেক্ষা করতে হবে। লুকের ভেতরে, এটি শুধু লোড সিমুলেশন করার জন্য র্যান্ডম, অর্থহীন গণনা করে। অবশেষে, এটি হিসাবগুলির ফলাফল ফেরত দেয়। ফাংশনটি কোনও উপকারী কাজ করে না, কিন্তু এটি ভারী লোডের একটি বাস্তব জগতের পরিস্থিতি সিমুলেশন করে. এই ফাংশনটি অন্য একটি সহজ ফাংশনের মধ্যে ব্যবহার করা হবে. একটি সাধারণ পরিস্থিতি কল্পনা করুন যেখানে আপনাকে একটি ডেটা সেটের মাধ্যমে লুপ করতে হবে এবং প্রতিটি আইটেমে সেই ভারী কাজটি প্রয়োগ করতে হবে। এজন্য আমরা একটি তৈরি করবো। ফাংশন : heavyWork() function heavyWork () { const data = Array.from({ length: 200 }, (_, i) => i) const result = [] for (let i = 0; i < data.length; i++) { result.push(blockingTask(10)) } return result; } যেখানে পরবর্তী ঘটনা ঘটে: লাইন 2 এ, এটি 200 আইটেমের একটি পরিসর তৈরি করে, শুধু 0 থেকে 199 পর্যন্ত সংখ্যাগুলি। তারপরে, প্রক্রিয়াজাত মূল্যগুলি সংরক্ষণ করার জন্য একটি নতুন শূন্য "প্রাপ্তির" আকার তৈরি করা হয়। লাইন 5 একটি লুকে ঘোষণা করে যা ডেটা আর্চারের পুরো দৈর্ঘ্য দিয়ে যায়। লুকের ভেতরে, আমরা ব্লকিংTask() ফাংশনটি চালু করি, প্রতিটি উপাদানের জন্য 10 মিলিসেকেন্ডের কাজের সিমুলেশন করি, এবং ফলাফলটি "প্রাপ্তির" আকারে যোগ করা হয়। আবারও, আমি আপনাকে মনে করতে চাই যে, ডেমো জন্য, ব্লকিংTask() ফাংশনটি কোন সিমেন্টিক লোড বহন করে না। অবশেষে, এটি ফলাফল আকার ফেরত দেয়। কেবলমাত্র 10 মিলিসেকেন্ড প্রতিটি উপাদান, এবং শুধুমাত্র 200 উপাদান - কিন্তু একসঙ্গে, তারা 2 সম্পূর্ণ সেকেন্ডের জন্য প্রধান ট্রেড ব্লক করে। সমস্যা প্রদর্শন। এখনই সমস্যাটি শুধু তত্ত্বে নয়, বরং কর্মে দেখার সময় এসেছে. এটি এখনও একটি সম্পূর্ণ ডেমো নয় - সমস্যাটি স্পষ্টভাবে দেখতে সাহায্য করার জন্য এটি একটি সামঞ্জস্যপূর্ণ ভিজ্যুয়াল হিসাবে বিবেচনা করুন। এখানে আপনি যা দেখতে পারেন: বাম উইন্ডো, "নির্বাচন" নামে, আপনাকে প্রধান থ্রেড ব্লকিং চালু এবং বন্ধ করতে দেয় - অর্থাৎ ব্লকিংTask() ফাংশন সত্যিই চালু হচ্ছে কিনা। "Heavy Task" নামের উইন্ডোটি heavyWork() ফাংশন চালু করে. এটি এমন একটি উইন্ডো যা প্রধান থ্রেড ব্লকিং সক্রিয় হলে প্রতিটি উপাদানে blockingTask() ব্যবহার করে একটি আকার প্রক্রিয়াকরণ করে। এবং "লগার" নামক উইন্ডোটি কেবলমাত্র কনসোলের বর্তমান সময় লগ করে, মিলিসেকেন্ড সহ। চলুন দেখে নেওয়া যাক কী ঘটবে যখন ব্লকিং বন্ধ করা হয়, তাই কাজগুলি খুব হালকা. এটি কেবল 200 টি উপাদানগুলির একটি মেরুতে একটি লুপ, কোনও জটিল হিসাব ছাড়া। Main Thread আপনি কি পর্যবেক্ষণ: ব্যবহারকারী "OK" বোতামটি ক্লিক করে - heavyWork() ফাংশন চালু হয়, এবং অবিলম্বে ফিরে আসে। তারপর ব্যবহারকারী "লগ" বোতামটি তিনবার ক্লিক করে, বর্তমান সময়কে কনসোলে লগ করতে - টাইমস্ট্যাম্পগুলি অবিলম্বে প্রদর্শিত হয়, সময় একটি সামান্য পার্থক্য সঙ্গে। ব্যবহারকারী আবার heavyWork() ফাংশন চালু করে, এবং আবার, অবিলম্বে প্রতিক্রিয়া। অবশেষে, ব্যবহারকারী দুটি উইন্ডো বন্ধ করে দেয়, যা প্রকৃতপক্ষে ডোম থেকে সেই উপাদানগুলি সরিয়ে দেয়। এই ক্ষেত্রে, সবকিছু দ্রুত এবং প্রতিক্রিয়াশীল মনে হয়. ব্রাউজারটি ইন্টারেকশনগুলি পরিচালনা করতে কোন সমস্যা নেই, কারণ প্রধান ট্রেডটি বিনামূল্যে থাকে। চলুন, আমরা সুবিধা দেই অর্থাৎ, প্রতিটি অক্ষরের জন্য, প্রতিটি অক্ষরের জন্য, ফাংশনটি শুধুমাত্র 10 মিলি সেকেন্ডের দেরিতে কল করা হবে। Main Thread blockingTask() এবং এখন আপনি দেখতে পারেন যে ইউআই উপাদানগুলির সাথে ব্যবহারকারীর ইন্টারফেসটি কম নরম হয়ে গেছে, ইউআই ফ্রিজ এসেছে। ব্যবহারকারী "OK" বোতামটি চাপায়, এইভাবে heavyWork() ফাংশনটি চালু করে। এবং প্রথম দেরি যা ঘটেছে তা হল যে "OK" বোতামটি দৃশ্যমানভাবে চাপিত থাকে। কেন? কারণ ব্রাউজারটি পুনরায় পেইন্ট করতে পারে না যখন heavyWork() এখনও প্রধান থ্রেডটি ব্লক করছে। এই সময়ে, ব্যবহারকারী "লগ" বোতামটি চারবার ক্লিক করে - কিছুই ঘটেনি। ক্লিকগুলি নিবন্ধিত হয় এবং তাদের অপারেটরগুলি রেজিস্ট্রেশন করা হয়, কিন্তু ব্রাউজার প্রতিক্রিয়া করতে পারে না। শুধুমাত্র heavyWork() শেষ হওয়ার পরে আপনি কনসোল আউটপুট দেখতে পাবেন: প্রথমে heavyWork() ফলাফল, তারপর চারটি টাইমস্ট্যাম্পগুলি - সবগুলি একটি ভাগে মুদ্রিত হয়। পরে, ব্যবহারকারী আবার "OK" বোতামটি ক্লিক করে। একই আচরণ - স্টিক বোতাম। তারপর, যখন heavyWork() কাজ চলছে, তখন তিনি "X" আইকনটি ক্লিক করে তিনবার একটি উইন্ডো বন্ধ করার চেষ্টা করে। আবার, কোন দৃশ্যমান প্রতিক্রিয়া নেই। এবং অবশেষে, heavyWork() চালানোর আরেকটি প্রচেষ্টা এবং শেষ উইন্ডো বন্ধ করুন। এই সহজ ডেমোটি দেখায় কত দীর্ঘ কাজগুলি ব্যবহারকারীর ক্রিয়াকলাপগুলি প্রতিক্রিয়া দেওয়ার জন্য ব্রাউজারের ক্ষমতা ব্লক করে। যদিও প্রতিটি ব্লকিং কলটি মাত্র 10 মিলি সেকেন্ড লাগে, তাদের মধ্যে 200 এর একসঙ্গে চেইনিং 2 সেকেন্ডের ফ্রিজে ফলাফল করে। ব্যবহারকারী বোতামগুলির সাথে যোগাযোগ করতে পারে না, ইন্টারফেসটি পুনরায় পেইন্ট করে না। ইভেন্টগুলি রয়ে গেছে, কিন্তু কল স্ট্যাক পরিষ্কার না হওয়া পর্যন্ত প্রক্রিয়াকলাপ করা হয় না। এটি শুধুমাত্র একটি পারফরম্যান্স সমস্যা নয় - এটি একটি ব্যবহারকারীর অভিজ্ঞতা সমস্যা। এবং এটি ঠিক সেই ধরনের সমস্যা যা আমরা সমাধান করতে চাই - সমস্যা সমাধান। এখন যেহেতু আপনি সমস্যাটি বুঝতে পেরেছেন, আমরা সম্ভাব্য সমাধান সম্পর্কে কথা বলি। অবশ্যই, সর্বোত্তম কৌশলটি প্রথমে কোডটি কার্যকর রাখা এবং জিনিসগুলি দ্রুত ভাঙার মাধ্যমে দীর্ঘ কাজগুলি এড়ানো। তবে, আপনি দেখেছেন, জিনিসগুলি ঘটে। প্রতিক্রিয়া উন্নত করার জন্য বিভিন্ন workarounds এবং টিপস আবির্ভূত হয়েছে. কিন্তু তাদের সব পিছনে মূল ধারণা - এবং পিছনে এছাড়াও - এটি বেশ সহজ: Prioritized Task Scheduling API scheduler.yield() Break a task into smaller pieces or so-called chunks. এবং মাঝে মাঝে, ব্রাউজারের শ্বাস নেওয়ার জন্য বিরতি নিন। অন্য কথায়, আপনি প্রধান থ্রেডকে আরো জরুরি কাজ, যেমন ব্যবহারকারীর ইন্টারেক্টিভেশন বা আপডেট রেন্ডারিংয়ের মতো চালানোর সুযোগ দিন, এবং তারপর আপনি নিজের কাজ শেষ করতে ফিরে আসেন। এখানে কি ধারণা ফাংশনটি pseudocode এর মত দেখায়: heavyWork() function heavyWork() { // Do heavy work... /** * Take a breather! * Yield the execution to the Main Thread... * */ // Continue to do heavy work... } এখানে কী হচ্ছে: আপনি আপনার দায়িত্বের একটি অংশ পরিচালনা করেন। তারপর, আপনি থামান, ব্রাউজার অন্যান্য উচ্চ অগ্রাধিকার কাজ (যেমন UI আপডেট) পরিচালনা করার অনুমতি দেয়। ফাংশনটি যেখান থেকে থেমে গেছে সেখান থেকে চালিয়ে যান। পুরনো সমস্যা সমাধানের পদ্ধতি আগে দীর্ঘ ব্লকিং কাজ মোকাবেলা করার জন্য সবচেয়ে সাধারণ ট্রিকটি ব্যবহার করা হয়েছিল 0 (নো) দেরিতে এটি ডাকলে, আপনি তার কলবাক কাজের শেষে যোগ করেন। অন্য কথায়, আপনি ব্রাউজারকে বলুন: scheduler.yield() setTimeout() macrotasks "আপনি বাকি সবকিছু পরিচালনা করার পরে এই কোডটি চালান। "আপনি বাকি সবকিছু পরিচালনা করার পরে এই কোডটি চালান। এভাবে আপনি প্রধান ত্রুটি কঠোর কাজের টুকরা মধ্যে একটি সংক্ষিপ্ত শ্বাস দিতে পারেন. এখানে কি আপডেট ফাংশনটি এই পদ্ধতি ব্যবহার করে দেখতে পারে: heavyWork() async function heavyWork() { // Yield to Main Thread to avoid UI blocking before heavy work await new Promise(resolve => setTimeout(resolve, 0)) const data = Array.from({ length: 200 }, (_, i) => i) const result = [] // Interval at which execution will be yielded to the main thread (approx. ~ 25%). const yieldInterval = Math.ceil(data.length / 4) for (let i = 0; i < data.length; i++) { // Yield control to Main Thread to update UI and handle other tasks. if (i % yieldInterval === 0) { await new Promise(resolve => setTimeout(resolve, 0)) } result.push(threadBlockingEnabled ? blockingTask(10) : data[i]) } return result } এখানে কী ঘটছে তা ভেঙে ফেলুন: লাইন 3: একটি প্রতিশ্রুতি তৈরি করা হয় এবং তার সম্পাদক অবিলম্বে চালু হয়, একটি setTimeout() এর পরিকল্পনা করা হয়, যা ন্যূনতম দেরি সঙ্গে। টাইমআউট এর কলব্যাক (যা প্রতিশ্রুতি সমাধান করে) ম্যাক্রোটাস্কের চূড়ান্তে যোগ করা হয়। অপেক্ষা করার কারণে, বাকি async ফাংশনটি স্থগিত হয়। প্রযুক্তিগতভাবে, এই অব্যাহতিটি মাইক্রোটাস্কের চূড়ান্তে যোগ করা হয়, প্রতিশ্রুতি সমাধানের জন্য অপেক্ষা করে। জাভাস্ক্রিপ্ট ইঞ্জিনটি কল স্ট্যাক চেক করে - যখন এটি খালি হয়, ইভেন্ট লুপটি প্রবেশ করে। প্রথমত, এটি ম লাইন 9: আমরা কতবার আমরা প্রধান ত্রুটিতে প্রদান করতে চাই, কাজের প্রায় প্রতি 25%। Lines 13-15: Inside the loop, if the condition for yielding interval is met, execution is transferred to the main thread, that is, the technique is repeated, allowing the browser process user interactions or redraw the interface. setTimeout() মূলত, এই পদ্ধতি কাজ করে - এটি তুলনামূলকভাবে সহজ এবং প্রতিক্রিয়া উন্নত করে। সঠিক পরিকল্পনা করার জন্য তৈরি করা হয় না. এটি ম্যাক্রোটাস্ক্রিপ্টের রেকর্ডের শেষে কাজ স্থাপন করে, এবং সেই রেকর্ডে ইতিমধ্যে যা কিছুই আপনাকে অব্যাহত রাখতে পারে। setTimeout() For example, let’s say some other part of the page uses নিয়মিত দায়িত্ব পালন করুন: setInterval() setInterval(() => { /* Another heavy work... */ }) async function heavyWork() { // Yield to Main Thread to avoid UI blocking before heavy work await new Promise(resolve => setTimeout(resolve, 0)) const data = Array.from({ length: 200 }, (_, i) => i) const result = [] // Interval at which execution will be yielded to the main thread (approx. ~ 25%). const yieldInterval = Math.ceil(data.length / 4) for (let i = 0; i < data.length; i++) { // Yield control to Main Thread to update UI and handle other tasks. if (i % yieldInterval === 0) { await new Promise((resolve, reject) => setTimeout(resolve, 0)) } result.push(threadBlockingEnabled ? blockingTask(10) : data[i]) } return result } এখন আপনার নিজের কাজ - পরবর্তী টুকরা ফাংশন - এক বা একাধিক এই ইন্টারভিউ কলবাক দ্বারা দেরি হতে পারে. ব্রাউজারটি কেবল পরবর্তী লাইনে যা কিছু চালু করে, এবং আপনি অর্ডার নিয়ন্ত্রণ করতে পারবেন না. তাই যখন এক ধরনের আপনাকে ফেরত দেয়, আপনি সঠিকভাবে জানেন না কখন আপনি নিয়ন্ত্রণ ফিরে পাবেন। heavyWork() setTimeout() পরিস্থিতি মোকাবেলা করার কিছু উপায় আছে, সেটা হতে পারে। ফাংশন, যা আপনাকে পরবর্তী পেইন্টিংয়ের আগে কাজের পরিকল্পনা করতে দেয়। , এবং অনুরূপ ত্রুটি আছে. অথবা এটি একটি ব্রাউজার অনিয়মের সময় আপনার কোডটি চালু করে. এটি সম্পূর্ণরূপে একটি বিকল্প নয়, কিন্তু পটভূমি জন্য ভাল, কম গুরুত্বপূর্ণ কাজ, যা প্রধান ট্রেডটি আরো গুরুত্বপূর্ণ কাজগুলির জন্য বিনামূল্যে হতে সহায়তা করে। সাধারণত, আমরা এই ধরনের সমস্যার সমাধান এবং প্রতিরোধের জন্য অন্যান্য কৌশলগুলি আলোচনা করতে পারি। টেবিলে নিয়ে যান। requestAnimationFrame() setTimeout() requestIdleCallback() scheduler.yield() ট্যাগঃ ( – একটি আধুনিক উপায় অবসর প্রয়োগ, এবং প্রধান থ্রেডের নিয়ন্ত্রণ প্রদান, যা ব্রাউজার যে কোনও অপেক্ষাকৃত উচ্চ অগ্রাধিকার কাজ সম্পাদনা করতে দেয়, এবং তারপর যেখান থেকে এটি অব্যাহত রেখে চলতে। এক্সপ্রেসটি অর্জন করা হয়, বর্তমান ফাংশনের কার্যক্রম স্থগিত হয় যেখানে এটি কল করা হয়েছিল, এবং প্রধান ট্রেডকে নিয়ন্ত্রণ দেয়, এইভাবে বর্তমান কাজটি ভাঙা বা স্থগিত করে। scheduler.yield() await scheduler.yield() সৌন্দর্যের এরপর থেকেই এর অব্যাহততা বাকি থাকে র ্যাংকিংয়ের সামনের দিকে, যা চলতে থাকে। যেকোনো অপরিহার্য কাজের মধ্যে অন্য কোনও গুরুত্বপূর্ণ পার্থক্য নেই। এ পদ্ধতিতে যা , এই পুনর্গঠনগুলি সাধারণত যেকোনো নতুন কাজগুলির পরে চালানো হয় যা ইতিমধ্যে রেখে গেছে, সম্ভাব্যত প্রধান ট্রেডের উত্পাদন এবং তাদের সম্পূর্ণকরণের মধ্যে দীর্ঘ দেরি হতে পারে। scheduler.yield() scheduler.yield() BEFORE setTimeout() setTimeout() নিম্নলিখিত চিত্রটি দেখায় কিভাবে তিনটি পদ্ধতি বাস্তবে তুলনা করা হয়: In the first example, without yielding to the main thread: At first, the long " " runs uninterrupted, blocking the main thread and UI accordingly. Then, a user event is processed – a button click triggered during the execution of " ". And finally, " " is executed – callback scheduled earlier or during the execution of the long task. Task 1 Task 1 Task 2 setTimeout() In the second example, using as a yielding to the main thread: The execution queue is different. At first, the long " " runs. Then, when the yield to the main thread happens, " " pauses to let the browser breathe, and the button click is processed. But after the button click is processed, the callback will be executed first, which could have been scheduled in advance or during the execution of " ". And finally, only after that, the continuation of " " will be executed. setTimeout() Task 1 Task 1 setTimeout() Task 1 Task 1 In the last example, using : After the long " " has been paused and the user click event has been processed, then the continuation of " " is prioritized and runs before any queued tasks. scheduler.yield() Task 1 Task 1 setTimeout() In summary, is a more intelligent and predictable way to give the main thread breathing room. It avoids the risk of your code being pushed too far back in the queue and helps maintain performance and responsiveness, especially in complex applications. scheduler.yield() অগ্রাধিকার সুতরাং, আচরণে এই ধরনের পার্থক্য কী কারণ? এটি অগ্রাধিকার সম্পর্কে! ডেভেলপারদের হিসাবে, আমরা সাধারণত অগ্রাধিকারের ক্ষেত্রে ইভেন্ট লুপে কাজগুলি সম্পন্ন করার পরিকল্পনা সম্পর্কে ভাবি না। এবং কিন্তু যদি আপনি গভীরে তাকান, তাহলে আপনি লক্ষ্য করবেন যে খেলায় অন্তর্নিহিত অগ্রাধিকারও রয়েছে. উদাহরণস্বরূপ, একটি বোতাম ক্লিক ম্যানেজার, ব্যবহারকারীর ক্রিয়াকলাপ দ্বারা চালিত, সাধারণত একটি ক্যালিফোর্নিয়া, যদিও উভয়ই আগেই বলেছি, এটি একটি অংশ – একটি ব্যাপক এবং বৈশিষ্ট্য সমৃদ্ধ ইন্টারফেস যা তার নিজস্ব পৃথক সম্পূর্ণ আলোচনার যোগ্য এবং এই আলোচনার ক্ষেত্রে স্পষ্টভাবে অতিক্রম করে। যাইহোক, এটি তার প্রধান বৈশিষ্ট্যগুলির একটি উল্লেখ করা গুরুত্বপূর্ণ: একটি স্পষ্ট কাজ অগ্রাধিকার মডেলের প্রবর্তন। microtasks macrotasks setTimeout() macrotasks scheduler.yield() Prioritized Task Scheduling API "ব্যবহারকারী ব্লকিং" - সর্বোচ্চ অগ্রাধিকারগুলি যা সরাসরি ব্যবহারকারীর ইন্টারেক্টিভেশনকে প্রভাবিত করে, যেমন ক্লিকগুলি, ট্যাপগুলি এবং গুরুত্বপূর্ণ ইউআই অপারেশনগুলি পরিচালনা করা। "ব্যবহারকারী-দৃশ্যমান" - কাজ যা ইউআই দৃশ্যমানতা বা সামগ্রীকে প্রভাবিত করে তবে অবিলম্বে ইনপুটের জন্য গুরুত্বপূর্ণ নয়। "ফাঁদ" - এমন কাজ যা জরুরি নয় এবং বর্তমান ব্যবহারকারীর অভিজ্ঞতাকে প্রভাবিত করে না এবং ব্যবহারকারীর কাছে দৃশ্যমান নয়। ডিফল্টের জন্য, ‘এ’ অগ্রাধিকার, অথবা বিস্তারিত উপরের থেকে একটি নির্দিষ্ট অগ্রাধিকার সঙ্গে কাজ পরিকল্পনা করার জন্য নির্ধারিত পদ্ধতি. যদিও এটি এই পদ্ধতি সম্পর্কে বিস্তারিত এখানে যাবেন না, এটা উল্লেখ করা উচিত যে যদি এর ভেতর থেকে একটি পরিকল্পনা করা হয়েছে। তিনি তার অগ্রাধিকার পেয়েছেন। scheduler.yield() user-visible Prioritized Task Scheduling API postTask() scheduler.yield() postTask() কিভাবে সিস্টেমটি ব্যবহার করবেন (সম্পাদনা) একবার আপনি বুঝতে পারেন কিভাবে সবকিছু কাজ করে - কাজের ধরন, দীর্ঘ ব্লকিং অপারেশন দ্বারা উত্সাহিত সমস্যা, এবং অগ্রাধিকার, ব্যবহার কিন্তু এটি বুদ্ধিমান এবং যথাযথ সাবধানে ব্যবহার করা উচিত. এখানে একটি আপডেট সংস্করণ ফাংশন ব্যবহার বর্তমানে, পরিবর্তে আপনাকে শুধু ফোন করতে হবে বাকি অংশটি বাকি থাকবে না। scheduler.yield() heavyWork() scheduler.yield() setTimeout() await scheduler.yield() async function heavyWork() { // Yield to Main Thread to avoid UI blocking before heavy work await scheduler.yield() const data = Array.from({ length: 200 }, (_, i) => i) const result = [] // Interval at which execution will be yielded to the main thread (approx. ~ 25%). const yieldInterval = Math.ceil(data.length / 4) for (let i = 0; i < data.length; i++) { // Yield control to Main Thread to update UI and handle other tasks. if (i % yieldInterval === 0) { await scheduler.yield() } result.push(threadBlockingEnabled ? blockingTask(10) : data[i]) } return result } Now, when a user starts a ফাংশন ব্যবহার ‘আমাদের মধ্যে পার্থক্য অবিলম্বে দৃশ্যমান। " বোতাম আটকে না, এবং দ্বিতীয়ত, ব্যবহারকারী ইভেন্ট ক্লিক করুন " " বোতামগুলি সফলভাবে প্রক্রিয়াজাত করা হয়, যা ব্যবহারকারীর পৃষ্ঠার সাথে ইন্টারেক্টরিংকে অবরুদ্ধ করে না। heavyWork() scheduler.yield() OK Log অর্থাৎ, প্রথমে, ফাংশন চালু করা হয়েছিল, এবং বোতামটি পুনরায় প্রদর্শন করা হয়েছিল, যখন এই ভারী কাজটি সম্পন্ন করা হয়েছিল, ব্যবহারকারী " " বোতাম. ইভেন্টটি সফলভাবে প্রক্রিয়াজাত করা হয়েছিল, এবং ডেটা কনসোলে প্রিন্ট করা হয়েছিল। ফাংশনটি অব্যাহত ছিল, এবং তার চূড়ান্ত ফলাফল কনসোলটিতে প্রিন্ট করা হয়েছিল। সংক্ষেপে, আপনি আপনার ব্রাউজারকে শুধুমাত্র একটি লাইন দিয়ে একটি বিরতি দিতে পারেন। heavyWork() Log heavyWork() Log ডেমো কার্যকারিতা বর্ণনা এখন যেহেতু আপনি তত্ত্বটি অনুসন্ধান করেছেন, তাহলে অনুশীলন করতে চলুন এবং একটি বাস্তব কাজের ডেমো দেখুন. এটি একটি সিমুলেশন ব্যাংকিং অ্যাপ্লিকেশন. অবশ্যই, এটি কল্পিত এবং সহজতর, কিন্তু এটি বাস্তব জটিলতার যথেষ্ট ধারণ করে যা আপনাকে বুঝতে সহায়তা করে যে কীভাবে মৌলিক ট্রেড ব্লকিং ইন্টারেক্টিভিটি প্রভাবিত করে, এবং কিভাবে সাহায্য করতে পারেন। scheduler.yield() এখানে ব্যবহারকারী ইন্টারফেসে কি দেখে: – By default, the account balance is hidden behind a placeholder of asterisks. This is a familiar pattern in real banking apps, where sensitive information is hidden unless explicitly revealed by the user. A button labeled " " toggles visibility. Balance section Show balance – A visual representation of a bank card, shown front side by default, where some details are displayed: card type in the top left corner, last 4 digits of the card, the cardholder's name, and payment system, at the bottom right corner of the card. There are two buttons to the right of the card: Bank card – which flips the card when clicked. The back side of the card reveals sensitive card data like its full number, expiration date, and CVV code. Although the card number is generally not considered private information, some applications still prefer not to show the full number by default, but only if the user initiates it. However, I know and even use banks that generally do not allow you to see the bank card number in the application. Show card details – by clicking this button, this feature supposedly generates a list of transactions on the card and displays them in the table below. It imitates the real functionality where users can generate reports on bank card transactions. In reality, these reports can be complex tables with many customizable filters and the ability to download the report as a file. Such operations might involve heavy computations, process a huge amount of data, making them resource-intensive and time-consuming. For the sake of the demo, it's simplified. Under the hood, the " " button triggers the previously discussed function, which simply blocks the main thread using the function, which was also discussed above. After that, static mock transaction data is simply rendered into the table. Generate report Generate report heavyWork() blockingTask() অ্যাপ্লিকেশনের আচরণ বামপাশের কনফিগারেশন প্যানেলের বিভিন্ন সেটিংস ব্যবহার করে কাস্টমাইজ করা যেতে পারে. আপনি পূর্ববর্তী স্ক্রিনশটগুলিতে এর সহজ সংস্করণ লক্ষ্য করতে পারেন. এখন সময় এসেছে এটি কী করে তা ব্যাখ্যা করার: প্রধান থ্রেড ব্লকিং – মূল থ্রেডটি ব্লক করা হবে কিনা তা নির্ধারণ করে. প্রকৃতপক্ষে, যখন এই বিকল্পটি সক্রিয় করা হয় তখন BlockingTask() ফাংশনটি চালু হয়। Scheduler.yield() – Scheduler.yield() ব্যবহার করা হয় কিনা তা সংশোধন করে। ডাটা মেরি দৈর্ঘ্য – heavyWork() ফাংশন দ্বারা কতগুলি উপাদান বারবার নিয়ন্ত্রণ করে. যত বেশি উপাদান, তত বেশি সময় লাগে। ব্লকিং টাইম দৈর্ঘ্য - সংজ্ঞায়িত করে কত মিলিসেকেন্ড প্রতিটি আকারের উপাদান প্রক্রিয়াকরণ করতে লাগে। আয়তন ইন্টারফেস – সংজ্ঞায়িত করে কিভাবে প্রায়ই scheduler.yield() ডাকা হয়, আয়তনের মাধ্যমে অগ্রগতি একটি শতাংশ হিসাবে। অর্থাৎ, এই সংখ্যাটি যত কম, তত বেশি প্রায়ই এটি ডাকা হবে। পূর্ববর্তী উদাহরণগুলিতে, আমরা একটি 10ms দেরি এবং 25% ইন্টারফেসের সাথে 200-অলিমেন্ট আয়তন ব্যবহার করেছি - অতিরিক্ত দেরি ছাড়াই দৃশ্যমান প্রভাবের জন্য একটি ভাল ভারসাম্য। প্রদর্শনী সমস্ত কার্যকারিতা এবং কনফিগারেশন সাজানোর পরে, আসুন একটি বাস্তব ব্যবহার পরিস্থিতিতে হাঁটুন এবং দেখি কীভাবে মৌলিক থ্রেড ব্লকিং ব্যবহারকারীর অভিজ্ঞতা প্রভাবিত করে। ব্লক এবং অক্ষমতা . আমরা সামান্য মেরু দৈর্ঘ্য বৃদ্ধি করবে, তাই ভারী অপারেশন দীর্ঘ সময় নেয়, আমাদের প্রভাবগুলি পর্যবেক্ষণ করার জন্য সময় দেয়। " বোতাম. দৃশ্যগুলির পেছনে, এই ফাংশন, যা 1000 টি উপাদান প্রক্রিয়াকরণ করে, যেখানে প্রতিটি উপাদান 10 মিলিসেকেন্ড লাগে। Main Thread scheduler.yield() Generate report heavyWork() দেখে নিন কী ঘটেছে: The » " বোতাম আটকে থাকে, এটি অপসারণ করে না, এবং ইউআই পুনরায় রিডার করে না। ‘তখন’ " বোতাম, কিন্তু কিছুই প্রতিক্রিয়া. ইন্টারফেসটি সম্পূর্ণরূপে ফ্রিজ করা হয়, কোন অ্যানিমেশন নেই, কোন প্রতিক্রিয়া নেই, কোন অগ্রগতি অনুভূতি নেই. এটি একটি খারাপ ব্যবহারকারীর অভিজ্ঞতার একটি ক্লাসিক উদাহরণ। অ্যাপ্লিকেশনটি ফ্রিজ করা হয়, যদিও প্রযুক্তিগতভাবে এটি এখনও কাজ করছে। Generate report Show card details Show balance এই দুর্বলতাগুলোকে আমরা ব্যবহার করি। কিছু কনফিগারেশন সংশোধন করে. এখানে কনফিগারেশন এখন দেখতে: এখনও ব্লক করা হয়েছে. এইবার, ব্যবহার করার বিকল্প অ্যাপ্লিকেশনটি সক্ষম করা হয়. আকারের দৈর্ঘ্য সামান্য বৃদ্ধি করা হয়, শুধুমাত্র স্পষ্টতার জন্য। ব্লকিং সময় একই থাকে, 10 মিলিসেকেন্ড। প্রতিক্রিয়া ইন্টারফেস নরম প্রতিক্রিয়া জন্য 5% পর্যন্ত হ্রাস করা হয়, যেহেতু মেরু দৈর্ঘ্য বৃদ্ধি করা হয়েছে। scheduler.yield() Main Thread scheduler.yield() scheduler.yield() এবং এখন আপডেট কনফিগারেশনের সাথে, একই ব্যবহারকারী প্রবাহ সম্পূর্ণরূপে আলাদা দেখায়। " বোতামটি ক্লিক করা হয়েছে, এটি সঠিকভাবে পুনরায় প্রদর্শন করে এবং লোডিং অ্যানিমেশন প্রদর্শিত হয়। রিপোর্টটি উত্পাদিত হচ্ছে, ব্যবহারকারী সফলভাবে ইন্টারফেসের সাথে ইন্টারফেস করে: তারা কার্ডটি ফ্লিপ করতে পারে এবং ভারসাম্যটি স্থানান্তর করতে পারে। অ্যাপ্লিকেশনটি প্রতিক্রিয়াশীল থাকে, এমনকি যদি অ্যানিমেশনগুলি সামান্য কম নরম হয় তবে এটি পূর্ববর্তী ফ্রিজের তুলনায় একটি বিশাল পদক্ষেপ। অবশ্যই, প্রকৃত বাস্তবায়ন আরও অপ্টিমাইজ করা যেতে পারে, কিন্তু এমনকি এই সহজ ফর্মে, পার্থক্য আকর্ষণীয়। Generate report scheduler.yield() Conclusion. সুতরাং, আজ আপনি আপনার ব্রাউজার একটি বিরতি দেওয়ার সম্পর্কে শিখেছেন, উপস্থাপনের গুরুত্ব উচ্চতর অগ্রাধিকারের কাজগুলি সম্পাদনা করার জন্য, এবং এই প্রযুক্তিগুলির সুবিধা এবং অসুবিধাগুলি। কিন্তু আমার লক্ষ্য ছিল আপনাকে একটি শক্তিশালী ভিত্তি দিতে, পরীক্ষা শুরু করার জন্য যথেষ্ট, এবং আপনার কোড ব্রাউজারের সাথে কীভাবে খেলছে তা সম্পর্কে ভিন্নভাবে ভাবতে শুরু করার জন্য যথেষ্ট। Main Thread Prioritized Task Scheduling API দরকারী বামপন্থী অনলাইন ডেমো – https://let-your-browser-take-a-breather.onrender.com/ ডেমো GitHub রিপোর্টার – https://github.com/WOLFRIEND/let_your_browser_take_a_breather চিত্র – https://drive.google.com/file/d/1FLKKPaseyypE3pVXXn7Cj0aWac3rCayn/view