امروزه تعامل بین برنامههای وب بر انواع درخواست HTTP متکی است. به عنوان مثال، فرض کنید یک برنامه فروشگاه آنلاین داریم و میخواهیم یک محصول جدید در آن ایجاد کنیم. برای این منظور، ما باید تمام اطلاعات لازم را پر کنیم و احتمالاً روی دکمهای تحت عنوان «ایجاد محصول» کلیک نماییم.
این عمل یک درخواست HTTP را به همراه تمام دادههای لازم به بکاند ارسال میکند و برنامه ما از آن دادهها برای ایجاد تغییرات در پایگاه داده استفاده مینماید. پس از اتمام عملیات، که میتواند موفقیتآمیز باشد یا نه، یک پاسخ HTTP به فرانتاند ارسال میشود که بر اساس وضعیت آن پاسخ، مطابق با آن عمل میکند.
هنگامی که این درخواستها و پاسخها بین بکاند و فرانتاند منتقل میشوند، باید از قالب خاصی پیروی داشته باشند تا هر دو طرف بتوانند منظور یکدیگر را درک کنند. HTTP برای این منظور ایجاد شده است و یک پروتکل شبکه استاندارد میباشد که برنامههای تحت وب را قادر میسازد تا یکدیگر را درک کرده و با همدیگر ارتباط برقرار نمایند.
چندین متد وجود دارد که میتوانیم برای ارسال درخواست HTTP از آنها استفاده کنیم و هر کدام از آنها وظایف متفاوتی را انجام میدهند، همانطور که در ادامه داریم:
متد GET
برای درخواست دادهها و منابع از سرور استفاده میشود. هنگامی که یک درخواست GET
ارسال میکنیم، پارامترهای کوئری در URL به صورت جفتهای name/value به شکل زیر تعبیه میشوند:
http://example.com/index.html?name1=value1&name2=value2
باید به این نکته توجه داشته باشیم که علامت ?
نشان دهنده آغاز لیستی از پارامترها است. هر پارامتر یک جفت name/value (name=value
) را تشکیل میدهد و علامت &
برای تقسیم دو پارامتر مختلف استفاده میشود.
متد POST
برای ارسال دادهها به سرور، یا افزودن یک منبع جدید یا بهروزرسانی یک منبع موجود مورد استفاده قرار میگیرد. پارامترها در بدنه درخواست HTTP ذخیره میشوند.
POST /index.html HTTP/1.1 Host: example.com name1=value1&name2=value2
این متد یک منبع را از سرور حذف میکند.
متد HEAD
دقیقاً مانند متد GET
عمل میکند با این تفاوت که پاسخ HTTP ارسال شده از سرور فقط شامل head است اما body را شامل نمیشود. این به این معنی است که اگر سرور با درخواست “OK” باشد، به ما پاسخ ۲۰۰ OK
را میدهد اما منبعی را که درخواست کرده بودیم نمیدهد. ما فقط میتوانیم منبع را با متد GET
بازیابی کنیم.
این متد زمانی که در حال تست کارکرد سرور هستیم بسیار مفید میباشد. گاهی اوقات، انتقال منبع ممکن است زمان زیادی طول بکشد، اما برای اهداف آزمایشی فقط به یک پاسخ ۲۰۰ OK
نیاز داریم تا بدانیم همه چیز به درستی کار میکند یا نه.
متد PUT
برای بهروزرسانی منابع موجود استفاده میشود و با یک تفاوت کوچک بسیار شبیه به متد POST
است. وقتی منبعی را که از قبل وجود دارد PUT
کنیم، منبع قدیمی بازنویسی میشود؛ و ایجاد چندین درخواست PUT
یکسان، همان اثری را خواهد داشت که یک بار آن را انجام دهیم.
وقتی منابع یکسانی را POST
میکنیم، هر بار که درخواست ارسال میگردد، آن منبع کپی میشود.
برای مدت زمان طولانی، جامعه جاوااسکریپت فاقد یک روش استاندارد برای ارسال درخواستهای HTTP بود. برخی از افراد از XMLHttpRequest
با نام مستعار AJAX استفاده میکردند، در حالی که برخی دیگر استفاده از کتابخانههای خارجی مانند Axios یا jQuery را ترجیح میدادند.
Fetch API در سال ۲۰۱۵ به عنوان روشی مدرن، ساده و استاندارد برای ایجاد درخواستهای HTTP با استفاده از جاوااسکریپت معرفی شد که به صورت native پشتیبانی میشود. بنابراین نیازی به نصب کتابخانههای third-party وجود ندارد.
Fetch API مبتنی بر promise است، به این معنی که یک سینتکس تمیز و مختصر برای نوشتن عملیات asynchronous ارائه میدهد. به عنوان مثال، به این صورت است که میتوانیم یک درخواست GET
با استفاده از fetch API ارسال نماییم.
fetch("https://jsonplaceholder.typicode.com/users") .then((response) => { // If the response is not 2xx, throw an error if (!response.ok) { throw new Error("Network response was not ok"); } // If the response is 200 OK, return the response in JSON format. return response.json(); }) .then((data) => console.log(data)) // You can continue to do something to the response. .catch((error) => console.error("Fetch error:", error)); // In case of an error, it will be captured and logged.
همچنین میتوانیم گزینههای سفارشی مانند headers سفارشی، توکنهای authorization و غیره را به درخواست اضافه کنیم.
fetch("https://jsonplaceholder.typicode.com/users", { headers: { "Content-Type": "application/json", "Authorization": "your-token-here", }, credentials: "same-origin", }) .then(. . .);
هنگام ارسال درخواست POST
، همه چیز کمی پیچیدهتر میشود زیرا، باید دادهها را با request body به سرور ارسال نماییم. این موضوع ممکن است بسته به نوع دادهای که ارسال میکنیم و مورد استفاده خاص ما پیچیده شود.
به عنوان مثال، کد زیر دادههای JSON را به بکاند ارسال میکند:
fetch("https://jsonplaceholder.typicode.com/users", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ name: "John Doe", email: "johndoe@example.com", }), });
در اینجا باید به چند نکته توجه کنیم. اول از همه، ما باید به صراحت method
درخواست را مشخص کنیم. اگر این را انجام ندهیم، به طور پیشفرض از متد GET
استفاده میشود.
همچنین request body فقط دادههای string را میپذیرد، بنابراین باید قبل از اختصاص دادن هر مقداری به request body از متد stringify()
برای تبدیل JSON به string استفاده کنیم.
علاوه بر این، مهم است که حتما header Content-Type
را درج کنیم تا دریافت کننده بداند که چگونه باید request body را تجزیه کند.
با این حال، مسائل معمولاً در عمل پیچیدهتر هستند. به عنوان مثال، هنگام کار با وب فرمها، به جای JSON، احتمالاً از encoding فرم x-www-form-urlencoded
استفاده میکنیم، در این صورت درخواست میتواند به این صورت ارسال شود. به عنوان مثال:
document.addEventListener("DOMContentLoaded", function () { const form = document.querySelector("form"); const usernameInput = document.getElementById("username"); const emailInput = document.getElementById("email"); const formData = new URLSearchParams(); usernameInput.addEventListener("input", function () { formData.set("username", usernameInput.value); }); emailInput.addEventListener("input", function () { formData.set("email", emailInput.value); }); form.addEventListener("submit", async function (event) { event.preventDefault(); // Prevent the default form submission action await fetch("https://jsonplaceholder.typicode.com/users", { method: "POST", body: formData.toString(), headers: { "Content-Type": "application/x-www-form-urlencoded", }, }); }); });
اگر نیاز داریم تا فایلها را در بکاند آپلود کنیم، لازم است به جای آن از encoding فرم multipart/form-data
استفاده نماییم.
document.addEventListener("DOMContentLoaded", function () { const form = document.getElementById("myForm"); const usernameInput = document.getElementById("username"); const emailInput = document.getElementById("email"); const pictureInput = document.getElementById("picture"); const formData = new FormData(); usernameInput.addEventListener("input", function () { formData.set("username", usernameInput.value); }); emailInput.addEventListener("input", function () { formData.set("email", emailInput.value); }); pictureInput.addEventListener("change", function () { formData.set("picture", pictureInput.files[0]); }); form.addEventListener("submit", async function (event) { event.preventDefault(); // Prevent the default form submission await fetch("https://jsonplaceholder.typicode.com/users", { method: "POST", body: formData, }); }); });
باید به این نکته توجه داشته باشیم که هنگام استفاده از FormData()
برای ساخت request body، Content-Type
در multipart/form-data
قفل میشود. در این مورد، نیازی به تنظیم header Content-Type
سفارشی نداریم.
درخواست PUT
مشابه POST
عمل میکند، اما باید method
را روی PUT
تنظیم کنیم.
fetch("https://jsonplaceholder.typicode.com/users", { method: "PUT", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ id: "123" name: "John Doe", email: "johndoe@example.com", }), });
در واقع، ما باید یک id
یا هر کلید دیگری ارائه دهیم که این امکان را فراهم کند تا بتوانیم رکورد مورد نظر خود را برای بهروزرسانی در بکاند پیدا کنیم.
درخواست DELETE
مشابه PUT
کار میکند، اما باید به خاطر داشته باشیم که method
را روی DELETE
تنظیم کنیم.
fetch("https://jsonplaceholder.typicode.com/users/123", { method: "DELETE", });
و به طور مشابه، به یاد داشته باشیم که یک id
ارائه کنیم تا برنامه بکاند بداند کدام رکورد را حذف کند.
علاوه بر fetch()
، امکان ایجاد درخواست HTTP با استفاده از XMLHttpRequest
نیز وجود دارد. مثال زیر نحوه ایجاد یک درخواست GET
به endpoint https://jsonplaceholder.typicode.com
را نشان میدهد.
var xhr = new XMLHttpRequest(); xhr.open("GET", "https://jsonplaceholder.typicode.com/users", true); xhr.onload = function () { if (xhr.status >= 200 && xhr.status < 300) { console.log(JSON.parse(xhr.responseText)); } else { console.error("Error:", xhr.statusText); } }; xhr.onerror = function () { console.error("Request failed"); }; xhr.send();
سینتکس این روش کمی پیچیدهتر است، زیرا XMLHttpRequest
برای کار با عملیات asynchronous به توابع callback متکی است. این بدان معناست که نتیجه به راحتی میتواند به callback hell منجر شود، که در آن ما لایه به لایه از توابع callback را داریم که خواندن و نگهداری کد را دشوار میکند.
با این حال، XMLHttpRequest
مزایایی هم دارد. با توجه به این واقعیت که XMLHttpRequest
در مقایسه با fetch()
بسیار قدیمیتر است، از این رو، پشتیبانی گستردهای دارد. زمانی که برنامه وب ما نیاز دارد که با مرورگرهای قدیمی سازگار باشد، باید از XMLHttpRequest
استفاده کنیم.
جدا از متدهای built-in، ما میتوانیم درخواستهای HTTP را با استفاده از کتابخانههای third-party نیز ارسال کنیم. به عنوان مثال، نحوه ارسال درخواست GET
با استفاده از jQuery به صورت زیر میباشد:
$.get("https://api.example.com/data", function (data) { console.log(data); }).fail(function (error) { console.error("Error:", error); });
jQuery یکی از محبوبترین کتابخانههای جاوااسکریپت است. هدف آن رفع بخشی از جاوااسکریپت است که استفاده از آن دشوار میباشد و در این زمینه بسیار موفق بوده است.
در سالهای اخیر، jQuery محبوبیت خود را از دست داده است زیرا vanilla جاوااسکریپت در طول سالها بهبود پیدا کرده و مشکلاتی که قبلاً افراد را آزار میداد اکنون برطرف شده است. بنابراین، این کتابخانه دیگر گزینه اصلی برای ایجاد برنامههای جاوااسکریپت نیست.
از طرف دیگر، میتوانیم با Axios کار کنیم، که یک کلاینت HTTP مبتنی بر promise است و مانند fetch()
عمل میکند، و برای مدت طولانی قبل از آمدن fetch()
مورد توجه توسعهدهندگان قرار گرفته بود.
axios .get("https://api.example.com/data") .then((response) => console.log(response.data)) .catch((error) => console.error("Axios error:", error));
Axios و fetch()
سینتکس بسیار مشابهی دارند زیرا هر دو مبتنی بر promise هستند. تفاوت اصلی بین آنها این است که fetch()
یک متد داخلی است، در حالی که Axios از ما میخواهد که یک کتابخانه خارجی نصب کنیم.
با این حال، Axios از ویژگیهای بسیار غنیتری برخوردار است، زیرا با رهگیریهای درخواست و پاسخ، مدیریت خودکار JSON و زمانبندی داخلی همراه میباشد.
ما در این مقاله چهار راه مختلف برای ارسال انواع درخواست HTTP با استفاده از جاوااسکریپت را بررسی کردیم و بسته به پروژهای که داریم میتوانیم از هر کدام از آنها استفاده کنیم.
Fetch API روشی مدرن و استاندارد برای ایجاد درخواستهای HTTP با استفاده از جاوااسکریپت است که یک سینتکس نسبتاً ساده دارد که نگهداری پروژه ما را آسانتر میکند.
XMLHttpRequest
روش قدیمی برای ارسال درخواستهای HTTP میباشد. استفاده از این روش معمولاً برای پروژههای جدید توصیه نمیشود، اما اگر پروژه ما باید با مرورگرهای قدیمی سازگار باشد، XMLHttpRequest
ممکن است همچنان مفید باشد.
jQuery یک پکیج خارجی است که میتواند کارهای زیادی از جمله ارسال درخواستهای HTTP را انجام دهد. اگرچه اهمیت jQuery در سالهای اخیر کمرنگ شده است، اما هنوز در بسیاری از پروژههای قدیمی مورد استفاده قرار میگیرد و ممکن است در کار خود به عنوان یک توسعهدهنده جاوااسکریپت با آن مواجه شویم.
Axios یک کتابخانه third-party است که برای ارسال درخواستهای HTTP استفاده میشود. این کتابخانه سینتکس بسیار شبیه به fetch API دارد اما دارای ویژگیهای بسیار پیشرفتهتری میباشد. این ما هستیم که باید تصمیم بگیریم که آیا در پروژه خود به این ویژگیها نیاز داریم یا خیر. اگر نه، به طور کلی توصیه میشود به جای آن از fetch()
استفاده کنیم.