Time ছাড়া Timeout
মাঝেমধ্যে পোলাপান ক্লাসে দুষ্টুমি করলে স্যার ক্লাস থেকে বের করে দেয়। শাস্তিস্বরূপ একজনকে বের করে দেয়ার পর বাকিরা কিন্তু বসে থাকে না; বরং ক্লাস কিন্তু চলতে থাকে। অনেক সময় স্যার কাউকে পাঁচ মিনিটের জন্য আবার কাউকে ৩০ মিনিটের জন্য রুম থেকে বের করে দেয়।
এই টাইম-আউট নিয়ে কথা বলার আগে একটু আগের কথায় ফেরত যাই।
একটু আগে বলছিলাম, জাভাস্ক্রিপ্ট সিরিয়াল অনুসারে ওপর থেকে নিচে লাইন বাই লাইন এক্সিকিউট হয়, যেটাকে আমরা Synchronous বা Single-threaded বলছি। সেটা সত্যি, তবে সেটার পাশাপাশি আরেকটা কিন্তু আছে। সেটা দেখার জন্য মাঝখানে একটা setTimeout ফাংশনকে কল করে দিবি। এই setTimeout ফাংশনকে কল করার সময় মিনিমাম একটা কলব্যাক ফাংশন তোকে দিতে হবে। নিচে আমি setTimeout-এর ভিতরের কলব্যাক ফাংশনের ভিতরে শুধু 3-কে কনসোল লগ করতেছি।
console.log(1);
console.log(2);
setTimeout(()=>{
console.log(3)
});
console.log(4);
console.log(5);
console.log(6);
Output: 1 2 4 5 6 --------- 3দেখতেছস, 3 সবার শেষে আউটপুটে দেখাচ্ছে। এটা কেন হচ্ছে, সেটা একটু পর আলোচনা করতেছি। তবে তার আগে setTimeout-এর সেকেন্ড প্যারামিটার হিসেবে 4000 সেট করে দে।
console.log(1);
console.log(2);
setTimeout(()=>{
console.log(3)
}, 4000);
console.log(4);
console.log(5);
console.log(6);
Output: 1 2 3 4 5 6 --------- 3এখন এটাকে রান করলে দেখবি, প্রথমে আউটপুটে 3 ছাড়া সবকিছুই দেখাচ্ছে, কিন্তু তারপর 4 সেকেন্ড পরে গিয়ে 3 দেখাবে। এর কারণ হচ্ছে, আমরা setTimeOut-এর সেকেন্ড প্যারামিটার হিসেবে 4000 মিলি সেকেন্ড (যা 4 সেকেন্ডের সমান) ওয়েট করতে বলেছি। তাই setTimeout-এর ভিতরে কলব্যাক ফাংশন চলার জন্য মিনিমাম 4 সেকেন্ড অপেক্ষা করবে।
যদি setTimeout-এ সেকেন্ড প্যারামিটার না থাকে, তাহলে সে 0 মিলিসেকেন্ড ধরে নেয় এবং সিরিয়ালমতো করার যে কাজগুলো আছে, সেগুলা আগে শেষ করে। তারপর setTimeout-এর ভিতরে ফাংশনকে কল করে।
আর যদি setTimeout সেকেন্ড প্যারামিটার থাকে, তাহলে বলে দেয়, setTimeout-এর সেকেন্ড প্যারামিটারের মান যত মিলিসেকেন্ড, তত মিলিসেকেন্ড পরে setTimeout-এর ভিতরের ফাংশনকে কল করবে।
অর্থাৎ জাভাস্ক্রিপ্ট স্বাভাবিকভাবে Synchronous হিসেবে চললেও এর মধ্যে মাঝে Asynchronous কিছু কাজ চলে আসতে পারে। Asynchronous মানে synchronous না। অর্থাৎ সিরিয়ালমতো একসাথে একটার পর একটা কাজ করবে না; বরং একসাথে একাধিক কাজ করবে। সিরিয়াল ব্রেক করবে। কাজ আগেপরে করবে। যেমনটা তুই দেখছস setTimeout করছে।
setTimeout-এর আরেকটা খালাতো ভাই আছে, সেটা হলো setInterval। এটা প্রায় কাছাকাছি কাজ করবে। এখানেও তুই দুইটা প্যারামিটার দিতে পারিস।
setInterval(()=>{
console.log('I M U')
}, 1000)
Output: I M U I M U I M U I M U —>এখন যদি এই জিনিসটা তুই তোর ব্রাউজারের console-এ গিয়ে দেখিস, দেখবি 1000 মিলিসেকেন্ড বা 1 সেকেন্ড পরপর I M U আউটপুট হিসেবে দেখাচ্ছে। আর একটার পর একটা আসতেই আছে। থামার কোনো নাম-গন্ধ নাই।
তবে কোন জিনিস কনসোল লগ করবে, তুই চাইলে সেটা চেইঞ্জ করতে পারবি। নিচের কোডের মতো জাস্ট ওপরে num নামে একটা ভেরিয়েবল ডিক্লেয়ার করছে, তারপর setInterval-এর ভিতরে num++ দিয়ে num ভেরিয়েবলের মান এক এক করে বাড়াতে পারবি।
let num = 0;
setInterval(()=>{
num++;
console.log(num);
}, 1000)
Output: 1 2 3 4 5 6 7 8 9 10 --------->এটাকে যদি তুই রান করিস, তোর console-এ দেখবি 1, 2, 3 এইভাবে প্রতিটা ভ্যালু 1000 মিলিসেকেন্ড বা 1 সেকেন্ড পরপর প্রিন্ট করছে এবং এই ফাংশন চলতেই থাকবে। এটা অনেকটা ঘড়ির কাঁটার মতো— চলতেই থাকবে, যতক্ষণ না তুই তাকে বন্ধ করিস।
এই setInterval কিন্তু এইটা আইডি রিটার্ন করে। তুই চাইলে সেটা একটা ভেরিয়েবলে রাখতে পারস। ধর, আমি intervalId নামক একটা ভেরিয়েবলে রাখলাম। তারপর setInterval-এর কলব্যাক ফাংশনের ভিতরে কোনো শর্তসাপেক্ষে clearInterval ফাংশনকে কল করে এই intervalId টা পাঠিয়ে দিবি। তাহলে যখন এই শর্ত পুরণ হবে, তখন setInterval স্টপ হয়ে যাবে।
let num = 0;
const intervalId = setInterval(() => {
num++;
console.log(num);
// Stop the interval when num reaches 5
if (num === 5) {
clearInterval(intervalId);
}
}, 1000);
Output: 1 2 3 4 5setTimeout vs setInterval
যদি তুই একবার কোনো কাজ delay দিয়ে চালাতে চাস (যেমন: ৫ সেকেন্ড পর নোটিফিকেশন দেখানো), তাইলে setTimeout ইউজ করবি। আর যদি তুই কোনো কাজ বারবার রিপিট করবি (যেমন: প্রতি ১ সেকেন্ডে ঘড়ির সময় দেখানো), তাহলে setInterval ইউজ করবি। এ ছাড়া setTimeout যেহেতু একবার চলবে, তাই একবার চলার পর আর বন্ধ করার কোনো দরকার নাই। তবে setTimeout চলার আগে বন্ধ করতে চাইলে বন্ধ করা যায়। অন্যদিকে setInterval চালু করিস, সেটা কিন্তু clearInterval না দিলে বারবার চলতেই থাকবে।
ফাইনাল কথা হচ্ছে— জাভাস্ক্রিপ্ট Single-threaded ভাষা, মানে একই সময়ে একটা কাজই করতে পারে। সে একসাথে একাধিক কাজ না করতে পারলেও একটা কাজের জন্য বসে থাকে না; বরং কিছু কাজ আছে, শুরু করে দিয়ে সেটা আরেকজনের ওপর দিয়ে রাখে, আর এইদিকে নিজের কাজ থাকলে সেগুলা চালাতে থাকে। এতে বাহির থেকে মনে হতে পারে, একাধিক কাজ একসাথে হ্যান্ডেল করতেছে। আসলে সে Asynchronous-এ কিছু কাজ হ্যান্ডেল করতেছে।
Practice:
- setTimeout() দিয়ে একটা ফাংশন তৈরি কর, যেখানে 3 সেকেন্ড পর “I wasted 3 seconds of my life by looking at screen and doing nothing” প্রিন্ট হবে।
- দুই সেকেন্ড পর পর একটা একটা করে সংখ্যা দেখাবে। 131 থেকে শুরু হবে এবং প্রতিবার দুই করে বাড়বে।
- দুই সেকেন্ড পরপর কনসোলে I am learning javascript লগ করবি এবং ৬ বার আউটপুট দেখানোর পর থেমে যাবে।
- setTimeout()-এর সেকেন্ড প্যারামিটার বাদ দিলে ডিফল্ট হিসেবে কত মাইক্রোসেকেন্ড ধরে নেয়?