ধরুন আমি ফেসবুক চালাচ্ছি, এখন একটা পোস্ট দেখে আমার ভালো লাগলো। এখন আমি এটাতে রিঅ্যাকশন দিতে চাচ্ছি। রিঅ্যাকশন বাটনে ক্লিক করার পর পুরো ফেসবুক আবার রিলোড হলো। কারণ আমি যে পোস্টে রিঅ্যাকশন দিয়েছি সে ডাটাকে ফেসবুকের সার্ভারে পাঠাতে হবে, আর তাই ব্রাউজার সে কাজ করতে গিয়ে পুরোপুরি রিলোড হলো। এখন প্রত্যেকবার যদি এমন রিঅ্যাকশন দিতে গিয়ে বারবার ফেসবুক পুরোপুরি রিলোড হয়, তাহলে ব্যাপারটা কেমন হলো? একে তো বারবার রিলোড হওয়ার কারণে ডাটাও বেশী খরচ হবে। একই সাথে ব্যাপারটা বিরক্তিকরও। আর এই সমস্যা সমাধানের জন্যেই এই অ্যাজাক্স টেকনিক এসেছে।
AJAX মানে হচ্ছে Asynchronous JavaScript And XML। অন্য কোনো ওয়েব সার্ভার অ্যাক্সেস করার জন্যে এটা একটা বিশেষ টেকনিক। অ্যাজাক্স এর এই টেকনিক মূলত কিছু জিনিসের সাহায্যে করা হয়ঃ
১। ব্রাউজারের স্পেশাল অবজেক্ট বা অ্যাপিআই, যেগুলোর সাহায্যে আমরা অন্য কোনো ওয়েব সার্ভারে রিকোয়েস্ট পাঠাতে পারি।
২। আর জাভাস্ক্রিপ্ট দিয়ে এইচটিএমএল ডমের সাহায্যে সেটার ফলাফল আমাদের ওয়েবপেজে দেখাতে পারি।
এখন বুঝলাম অ্যাজাক্স এর সাহায্যে এই কাজ করা যায়। কিন্তু এর সুবিধাটা কি? হ্যাঁ অ্যাজাক্সের কারণে আমরাঃ
আর এজন্যেই এখন আমরা ফেসবুকে রিঅ্যাকশন দিলেও সেই ডাটা ব্যাকগ্রাউন্ডেই ফেসবুক সার্ভারে চলে যায়, আবার আমাদের এখানেও সেটা আপডেট হয়। কোনোরকম রিলোড হওয়া ছাড়াই সব কাজ ব্যাকগ্রাউন্ডে চলে। এতে আমাদের ইউজার এক্সপেরিয়েন্সও যেমন ভালো হয়, তেমনি ডাটাও খরচ কম হয়। আর সবচেয়ে বড় কথা পুরো ব্যাপারটাই বাস্তব মনে হয়।
এখন এই টেকনিকের জন্যে আমাদের আরো ছোটো ছোটো কিছু ব্যাপারও জানতে হবে। আজকে আমরা সেই টেকনিকগুলোই দেখবো এবং একই সাথে এই অ্যাজাক্সের সাহায্যে আমাদের পেজে অন্য কোনো ওয়েব সার্ভারে রিকোয়েস্ট পাঠিয়ে ডাটা এনে এইচটিএমএল ডমের সাহায্যে শো করাবো।
আমরা আজকে এই লেখায় প্র্যাক্টিসের জন্যে একটা প্রোজেক্ট ব্যবহার করবো। এটা এখান থেকে ডাউনলোড করে আনজিপ করে নিবেন। তারপর আপনার পছন্দের কোড এডিটরে প্রোজেক্টটা ওপেন করে index.html
ফাইলটা ক্রোমে ওপেন করুন। একই সাথে ক্রোমের ডেভেলপার কন্সোলটাও ওপেন করে রাখবেন। আমরা আমাদের প্রোজেক্টের script.js
ফাইলের ভিতরে সব কোড লিখবো। আর কোড লিখে সেটার পরিবর্তন দেখতে হলে অবশ্যই script.js
ফাইলটা সেইভ করে ব্রাউজারে ওপেন করে রাখা ডকুমেন্টটা রিলোড করতে হবে।
অ্যাজাক্স রিকোয়েস্ট তৈরীঃ শুরু করার আগে প্রথমেই আমরা কিভাবে অ্যাজাক্স রিকোয়েস্ট তৈরী করবো সেটা দেখে নিবো। একটু আগেই বলেছিলাম ব্রাউজারের স্পেশাল অবজেক্ট আর অ্যাপিআই এর কথা যেগুলোর সাহায্যে আমরা অ্যাজাক্স রিকোয়েস্ট করতে পারি। সে স্পেশাল অবজেক্ট হচ্ছে XMLHttpRequest
। আমরা আজকে এটা ব্যবহার করেই সবকিছু দেখবো। আর ব্রাউজারে নতুন আরেকটা অ্যাপিআই, fetch
অ্যাপিআইও যুক্ত হয়েছে যেটার সাহায্যেই অনেকটা একইরকম কাজ করা যায়(নিত্যদিনের জাভাস্ক্রিপ্ট সিরিজে এই অ্যাপিআই নিয়ে আলোচনা করা হয়েছে)। তবে আমরা এখানে বিশেষ সুবিধার কারণে XMLHttpRequest
ই ব্যবহার করবো। এখন একটা রিকোয়েস্ট তৈরী করার আগেঃ
১। XMLHttpRequest
এর একটা ইন্সট্যান্স অবজেক্ট তৈরী করা,
২। রিকোয়েস্ট ওপেন করা,
৩। রিকোয়েস্ট পাঠানো এবং
৪। রিকোয়েস্টটা হ্যান্ডেল করা।
একটা সিম্পল রিকোয়েস্টঃ
var request = new XMLHttpRequest(); // ইন্সট্যান্স অবজেক্ট তৈরী
request.open('GET', 'url', true); // রিকোয়েস্ট ওপেন করা
request.send(); // রিকোয়েস্ট পাঠানো
// রিকোয়েস্ট হ্যান্ডেল
request.onreadystatechange = function handleRequest(){
console.log(request);
}
এখানে প্রথম লাইনে আমরা XMLHttpRequest
থেকে একটা অবজেক্ট তৈরী করলাম। তারপর দ্বিতীয় লাইনে রিকোয়েস্ট ওপেন করলাম সেই অবজেক্ট এর open()
মেথড দিয়ে। এখন এই মেথড কয়েকটা আর্গুমেন্ট নিবে। এগুলো খুবই গুরুত্বপূর্ণ। প্রথম আর্গুমেন্ট টা রিকোয়েস্ট অ্যাকশন টাইপ, রিকোয়েস্ট অ্যাকশন টাইপ GET
থেকে শুরু করে আরো কয়েক টাইপের হতে পারে। এই রিকোয়েস্ট অ্যাকশন টাইপও বিভিন্ন অর্থ প্রকাশ করার জন্যে ব্যবহার করা হয়। যেমন এই GET
রিকোয়েস্ট সহ আরো কয়েক টাইপের রিকোয়েস্ট আছেঃ
GET
: এই টাইপের রিকোয়েস্ট পাঠানো হয় কোনো সার্ভার থেকে ডাটা আনার জন্যেPOST
: এই টাইপটা পাঠানো হয় যদি আমরা সার্ভারে কোনো ডাটা ঢুকাতে চাইUPDATE
: এই টাইপ দিয়ে বুঝানো হয় আমরা সার্ভারে কোনো ডাটা আপডেট করতে চাচ্ছি।DELETE
: সার্ভারের কোনো ডাটা ডিলেট করার রিকোয়েস্টএই রিকোয়েস্টগুলো অর্থপূর্ণ রিকোয়েস্ট এর জন্যে ব্যবহার করা হয়। এদের মধ্যে ফাংশানালিটির তেমন কোনো পার্থক্য নাই। তবে আমরা সার্ভারের সাথে কিসের জন্যে রিকোয়েস্ট পাঠাচ্ছি সেটা বুঝার জন্যে এই টাইপগুলো ব্যবহার করা হয়, আর সার্ভারও এই টাইপগুলো বুঝতে পারে।
তারপর দ্বিতীয় আর্গুমেন্টটা হচ্ছে ইউআরএল, মানে আমরা যে সার্ভারে রিকোয়েস্ট পাঠাতে চাচ্ছি সেটার ঠিকানা। আর সবশেষ আর্গুমেন্টটা হচ্ছে আমরা এই রিকোয়েস্টটা অ্যাসিনক্রোনাস ভাবে করতে চাচ্ছি true
নাকি চাচ্ছি না false
সেটা বুঝাতে।
তারপরের লাইনে আমাদের রিকোয়েস্টটা পাঠানো হলো send()
দিয়ে। আর একদম শেষে আমরা যদি এই request
এর অবস্থার কোনো পরিবর্তন হয় তাহলে একটা ফাংশন রান করতে বলেছি। এই ফাংশনের ভিতরে আমরা request
টা লগ করেছি।
অ্যাজাক্স রিকোয়েস্ট দিয়ে ডাটা আনাঃ আমরা এখন এভাবে রিকোয়েস্ট তৈরী করে কিছু ডাটা আনবো। প্রথমে আমরা এই ওয়েবসাইটটা ব্যবহার করে এদের সার্ভার থেকে ডাটা আনবো। এই ওয়েবসাইটে গেলে কিছু ডিমো ডাটার জন্যে লিঙ্ক পাবেনঃ
এখান থেকে আমরা পোস্ট /posts
এর ডাটাগুলো অ্যাজাক্স রিকোয়েস্ট এর সাহায্যে আনবো। এই লিঙ্কে গেলে ডাটাগুলো সরাসরি ব্রাউজারেই দেখতে পাবেন। স্ক্রিপ্ট ফাইলটা ওপেন করে আমরা ডাটাগুলো আনবো এবং আপাতত কন্সোলে লগ করে দেখবোঃ
var request = new XMLHttpRequest();
request.open('GET', 'https://jsonplaceholder.typicode.com/posts', true);
request.send();
request.onreadystatechange = function handleRequest(){
console.log(request.responseText);
}
এখানে দেখবেন আমরা request
এর কোনোরকম পরিবর্তনে যে ফাংশনটা লাগিয়েছে সেটাতে আমরা request.responseText
লগ করেছি, কারণ সার্ভার থেকে আসা ডাটা ঠিক এখানেই পাওয়া যাবে তাই।
এটা লিখে স্ক্রিপ্ট ফাইল সেইভ করে ব্রাউজার রিলোড দিলে কন্সোলে দেখতে পাবেন ডাটাগুলো চলে আসছেঃ
জেসন(JSON): জেসন বা পুরোনাম জাভাস্ক্রিপ্ট অবজেক্ট নোটেশন(JavaScript Object Notation) হচ্ছে সিম্পলি স্ট্রিং। কিন্তু স্ট্রিং এমনভাবে সাজানো যেটা জাভাস্ক্রিপ্ট এর অবজেক্ট এর মতো দেখা যায়, কিন্তু ঠিক জাভাস্ক্রিপ্ট এর অবজেক্ট না। আমরা যদি এটার টাইপ দেখতে চাই তাহলে আমরা typeof
দিয়ে আমাদের অন্য সার্ভার থেকে আনা ডাটাগুলোর টাইপ দেখতে পারি, জাস্ট স্ক্রিপ্ট ফাইএল typeof
কিওয়ার্ডটা লাগিয়ে দিন ডাটা কন্সোল লগ করার সময়ঃ
var request = new XMLHttpRequest();
request.open('GET', 'https://jsonplaceholder.typicode.com/posts', true);
request.send();
request.onreadystatechange = function handleRequest(){
console.log(typeof request.responseText);
}
এবার স্ক্রিপ্ট ফাইলটা সেইভ করে ব্রাউজার রিলোড দেখতে পাবেনঃ
এটা স্ট্রিং কিন্তু জাভাস্ক্রিপ্ট এর বিল্ট-ইন কিছু ফাংশন আছে এই স্ট্রিংকে অবজেক্ট এ নেওয়ার জন্যে। অবজেক্ট এ নিলে আমরা একটা সুন্দর স্ট্রাকচার পাবো যেটা থেকে পরে বিভিন্নভাবে ডাটা বের করে এনে আমরা আমাদের পেজে দেখাতে পারবো। এরকম জেসন স্ট্রিং ডাটাকে অবজেক্ট এ নিতে চাইলে JSON.parse()
ব্যবহার করা হয়। এখন আমরা আমাদের উপরের কোডটা একটু মডিফাই করে একেবারে অবজেক্টই কন্সোলে লগ করতে চাইঃ
var request = new XMLHttpRequest();
request.open('GET', 'https://jsonplaceholder.typicode.com/posts', true);
request.send();
request.onreadystatechange = function handleRequest(){
console.log(JSON.parse(request.responseText));
}
এটা সেইভ করে ব্রাউজার রিলোড দিলে এরকম অবজেক্ট আকারে ডাটাগুলো পাবেন যেখানে ১০০টার মতো অ্যারে আছেঃ
রিকোয়েস্ট এর স্টেটঃ তবে আগে পরে একটু আশ্চর্যের কিছু জিনিস দেখতে পাবেন। সেগুলো হচ্ছে একদম প্রথম লাইনে একটা এরর। পরে ডাটাগুলো দুইবার লগ হয়েছেঃ
এটার কারণ কি? হ্যাঁ, কারণ জানতে হলে আমাদের আরেকটু গভীরে যেতে হবে। আমরা যে অ্যাজাক্স রিকোয়েস্ট করলাম সেটার কয়েকটা স্টেট আছে। আমরা request.onreadystatechange
ব্যবহার করেছি যাতে request
এ কোনো পরিবর্তন হলেই ফাংশনটা রান করে। এখন এই স্টেটেরও কয়েকটা লেভেল আছে যেগুলো request
এর ভিতরে readyState
নামে পাওয়া যায়ঃ
var request = new XMLHttpRequest();
console.log(request.readyState);
request.open('GET', 'https://jsonplaceholder.typicode.com/posts', true);
console.log(request.readyState);
request.send();request.onreadystatechange = function handleRequest(){
console.log(request.readyState);
}
আমরা কয়েকটা জায়গায় এই readyState
এর অবস্থা দেখবো, এটা কিভাবে পরিবর্তন হয় সেটা দেখবো। এটা সেইভ করে ব্রাউজার রিলোড দিলে এরকম আউপুট পাবেন কন্সোলেঃ
এখানে readyState
নাম্বার দিয়ে প্রকাশ করা হলেও এই নাম্বারগুলোর বিভিন্নরকমের মিনিং আছেঃ
0
— মানে রিকোয়েস্ট এখনো আরম্ভ করা হয়নি
1
— সার্ভারের সাথে কানেকশন তৈরী করা হয়েছে
2
— রিকোয়েস্ট পাঠানো হয়েছে
3
— রিকোয়েস্ট প্রসেস করা হয়েছে
4
— রিকোয়েস্ট সফলভাবে শেষ হয়েছে, রেসপন্স তৈরী
এখান আমাদের ডাটাগুলো পাওয়ার সবচেয়ে ভালো সময় হচ্ছে রিকোয়েস্ট readyState
4
এ থাকলে। আর আমরা এটা চেক না করেই ডাটা লগ করায় একবার এরর, আর দুইবার একই ডাটা দেখাচ্ছে। তাই আমরা এখন চেক বসিয়ে দিতে পারি ডাটা দেখানোর আগে যাতে এরকম সমস্যা তৈরী না হয়ঃ
var request = new XMLHttpRequest();
request.open('GET', 'https://jsonplaceholder.typicode.com/posts', true);
request.send();
request.onreadystatechange = function handleRequest(){
if(request.readyState === 4) {
console.log(JSON.parse(request.responseText));
}
}
এবার কন্সোলে দেখবেন সুন্দর করেই একবারই ডাটাগুলো দেখাচ্ছে কোনো এরর ছাড়াঃ
রিকোয়েস্ট রেসপন্সঃ এখন আমরা যদি ভুল কোনো ইউআরএল দিয়ে রিকোয়েস্ট করি তাহলেঃ
var request = new XMLHttpRequest();
request.open('GET', 'https://jeiwebsitenai.typicode.com/posts', true);
request.send();
request.onreadystatechange = function handleRequest(){
if(request.readyState === 4) {
console.log(JSON.parse(request.responseText));
}
}
এখন কন্সোলে এরকম এরর দেখতে পাবেনঃ
এর কারণ হচ্ছে আমাদের ইউআরএলই ভুল, তাই প্রথম এররটা ইউআরএল পাওয়া যায়নি সেটার উপর। আর দ্বিতীয়টা পাওয়া না যাওয়া ডাটার উপর অপারেশন চালানোর এরর। এটা হ্যান্ডেল করার জন্যেও request
অবজেক্ট এর আরেকটা প্রপার্টি আছে status
নামে। এটার মূলত আপনার রিকোয়েস্ট এর স্ট্যাটাস কোড স্টোর করে। একটা সফল রিকোয়েস্ট এর স্ট্যাটাস কোড হচ্ছে 200
,তার মানে আমরা এটাও চেক হিসেবে বসাতে পারি ডাটা দেখানোর আগেঃ
var request = new XMLHttpRequest();
request.open('GET', 'https://jeiwebsitenai.typicode.com/posts', true);
request.send();
request.onreadystatechange = function handleRequest(){
if(request.readyState === 4 && request.status === 200) {
console.log(JSON.parse(request.responseText));
}
}
এখন ইউআরএল ভুল হলে বা কোনো কারণে সার্ভারে কোনো সমস্যা হলেও আমাদের আর এরর দেখতে হবে না। এরই সাথে আমরা স্ট্যাটাস কোড ব্যবহার করে ডাটা না পাওয়া গেলে সেটার উপর কন্ডিশন দিয়ে আমাদের ইউজারকে অন্যকোনো ম্যাসেজ শো করাতে পারবো। এরকম কমন কিছু স্ট্যাটাস কোড আছেঃ
— 200
: সফল রিকোয়েস্ট
— 403
: আপনার পারমিশন নেই
— 404
: পাওয়া যায় নি
এই রিকোয়েস্টগুলোর প্রথম নাম্বারগুলোও একটা প্যাটার্ন মেইন্টেইন করেঃ
— 1xx
: ইনফরমেশন
— 2xx
: সাক্সেস
— 3xx
: রিডাইরেকশন
— 4xx
: ক্লাইন্ট এরর
— 5xx
: সার্ভার এরর
পেজে এ ডাটা দেখানোঃ আমরা এতক্ষন ডাটা উদ্ধার করলাম। এখন সেই ডাটা আমাদের ডকুমেন্ট এ দেখাবো। তার আগে রিকোয়েস্টটাকে কমপ্লিট করে নেইঃ
var request = new XMLHttpRequest();
request.open('GET', 'https://jsonplaceholder.typicode.com/posts', true);
request.send();
request.onreadystatechange = function handleRequest(){
if(request.readyState === 4 && request.status === 200) {
console.log(JSON.parse(request.responseText));
}
}
এখন কন্সোলে যদি দেখেন তাহলে দেখবেন ১০০টা অ্যারেরই কিছু প্রপার্টি আছে, তারমধ্যে title
টা আমরা লিস্ট আকারে আমাদের ডকুমেন্ট এ থাকা বক্সে দেখাবো। আমরা এটা এমনভাবে করবো, যদি কেউ এখানে থাকা LOAD POSTS বাটনে ক্লিক করে তাহলে আমরা অ্যাজাক্স রিকোয়েস্ট পাঠিয়ে সার্ভার থেকে ডাটা এনে এটার নিচেই লিস্ট আকারে দেখাবো।
তাই প্রথমে আমাদের বাটনটা সিলেক্ট করে নিতে হবেঃ
var loadPosts = document.getElementById('btn-click-me');
তারপর বক্সটাকেও সিলেক্ট করবো। এই বক্সেই চাইল্ড হিসেবে আমরা আমাদের লিস্টটা ঢুকাবোঃ
var box = document.getElementById('box');
এখন আমরা আমাদের বাটনে একটা ইভেন্ট লিসেনার লাগাবো আর সেই ইভেন্টে আমরা পোস্টগুলো অ্যাজাক্স রিকোয়েস্ট হিসেবে সার্ভার থেকে আনবোঃ
loadPosts.addEventListener('click', function() {
var request = new XMLHttpRequest();
request.open('GET', 'https://jsonplaceholder.typicode.com/posts', true);
request.send(); request.onreadystatechange = function handleRequest(){
if(request.readyState === 4 && request.status === 200) {
console.log(JSON.parse(request.responseText));
}
}
});
আমরা আগের রিকোয়েস্টাকেই বাটনের ক্লিকে যাতে ঘটে ঐরকম করে দিয়েছি। এখন স্ক্রিপ্ট ফাইল সেইভ করে ব্রাউজার রিলোড দিলে দেখবেন আর এটা সরাসরি রান করছে না। বাটনে ক্লিক করলেই কন্সোলে ফলাফল দেখতে পাবেন।
এখন আমরা কন্সোলে না, বরং বাটনের নিচে লিস্ট আকারে ফলাফল দেখতে চাচ্ছি। তাই আমরা সহজভাবেই আমাদের ডম ম্যানিপুলেশনের নলেজ দিয়ে সে কাজ করতে পারবোঃ
var loadPosts = document.getElementById('btn-click-me');
var box = document.getElementById('box');
var uList = document.createElement('ul');
loadPosts.addEventListener('click', function() {
var request = new XMLHttpRequest();
request.open('GET', 'https://jsonplaceholder.typicode.com/posts', true);
request.send();
request.onreadystatechange = function handleRequest(){
if(request.readyState === 4 && request.status === 200) {
var data = JSON.parse(request.responseText);
data.forEach(function(singleData) {
var list = document.createElement('li');
list.textContent = singleData.title;
uList.appendChild(list)
})
box.insertAdjacentElement('beforeend', uList);
}
}
});
কোডগুলো ভালো করে লক্ষ্য করুন, বেশী কিছু করা হয়নি এখানে। একদম সিম্পলভাবেই করা হয়েছে। এটা লিখে স্ক্রিপ্ট ফাইলটা সেইভ করে ব্রাউজার রিলোড দিয়ে যদি LOAD POSTS বাটনে ক্লিক করি, তাহলে দেখবেন এরকম লিস্ট আকারে আমাদের ডাটাগুলো চলে আসছেঃ
ব্যাস, হয়ে গেলো আমাদের অ্যাজাক্স রিকোয়েস্টের সাহায্যে পেজ রিলোড না করেই অন্য কোনো সার্ভার থেকে ডাটা নিয়ে আসার কাজ।