FA-TOOLS — Header Component
آموزش fetch api در جاوا اسکریپت

آموزش جامع Fetch API در جاوا اسکریپت: کاربردی و گام‌به‌گام

فهرست مطالب

  • Fetch API چیست و چگونه کار می‌کند؟
  • مقایسه Fetch API با XMLHttpRequest و Axios
  • ارسال درخواست GET (دریافت اطلاعات)
  • مدیریت خطاهای شبکه و status HTTP (نکته حیاتی)
  • ارسال داده به سرور با متد POST
  • متدهای PUT ،PATCH و DELETE
  • لغو درخواست‌ها و تعیین Timeout با AbortController
  • ارسال فایل و داده‌های Form-Data
  • عیب‌یابی سریع و رفع مشکلات رایج
  • پرسش‌های متداول

Fetch API متد استاندارد و بومی جاوا اسکریپت برای ارسال درخواست‌های شبکه و دریافت داده از سرور بدون نیاز به بارگذاری مجدد صفحه است. در این مقاله عملی، نحوه‌ی تعامل با REST API، مدیریت خطاهای پیش‌بینی نشده، لغو درخواست‌های طولانی و ارسال فرم‌ها را همراه با مثال‌های واقعی بررسی می‌کنیم تا به‌طور کامل بر ارتباط کلاینت و سرور مسلط شوید.

خلاصه سریع نکات کلیدی

  • تابع fetch() بر پایه Promise کار می‌کند و کدنویسی ناهمگام را بسیار ساده می‌سازد.
  • پاسخ‌های ۴۰۴ یا ۵۰۰ باعث reject شدن Promise نمی‌شوند؛ باید شرط response.ok را دستی بررسی کنید.
  • برای لغو درخواست یا تنظیم محدودیت زمانی (Timeout) از API بومی AbortController استفاده می‌شود.
  • هنگام ارسال داده‌های فرم با FormData، نباید هدر Content-Type را دستی مقداردهی کنید.

Fetch API چیست و چگونه کار می‌کند؟

Fetch API چیست و چگونه کار می‌کند؟

Fetch API یک رابط برنامه‌نویسی بومی در مرورگرهای مدرن است که امکان ارسال درخواست‌های HTTP (مانند GET و POST) به سرور را فراهم می‌کند. این ابزار به عنوان جایگزینی مدرن برای XMLHttpRequest معرفی شده و کاملاً مبتنی بر Promise کار می‌کند.

وقتی از fetch() استفاده می‌کنید، مرورگر یک Promise برمی‌گرداند که در صورت موفقیت‌آمیز بودن ارتباط شبکه، به یک شیء Response تبدیل می‌شود. ساختار خروجی این ابزار خوانایی کدهای شما را افزایش داده و ترکیب آن با async/await توسعه برنامه‌های وب را بسیار سریع‌تر می‌کند. برای آشنایی با موارد مشابه در توسعه وب، می‌توانید تکه‌کدهای کاربردی جاوا اسکریپت را در پروژه خود بررسی کنید.

مقایسه Fetch API با XMLHttpRequest و Axios

مقایسه Fetch API با XMLHttpRequest و Axios

انتخاب ابزار مناسب برای درخواست‌های شبکه به نیاز پروژه شما بستگی دارد. جدول زیر تفاوت‌های کلیدی Fetch API را با ابزارهای قدیمی و کتابخانه‌های جانبی نشان می‌دهد:

ویژگی توضیحات و عملکرد
پشتیبانی بومی (Native) بله، بدون نیاز به نصب هیچ package یا کتابخانه اضافی در مرورگر و Node.js 18 به بعد در دسترس است.
پایه مدرن بر اساس Promise بر خلاف XMLHttpRequest که بر پایه Callback است، Fetch کاملاً استاندارد async/await را پشتیبانی می‌کند.
پارس خودکار JSON خیر، برخلاف کتابخانه Axios، باید پاسخ را دستی با متد response.json() تبدیل کنید.
رفتار در خطاهای ۴۰۴ و ۵۰۰ درخواست رد (Reject) نمی‌شود و باید خصوصیت response.ok چک شود.

ارسال درخواست GET (دریافت اطلاعات)

ارسال درخواست GET (دریافت اطلاعات)

درخواست GET ساده‌ترین نوع درخواست شبکه است که برای دریافت داده از یک URL مشخص استفاده می‌شود. متد fetch() به‌صورت پیش‌فرض درخواست‌ها را با آدرس و ورودی‌های تنظیم‌شده روی GET قرار می‌دهد.

برای کار با خروجی، ابتدا باید داده‌های خام دریافتی از سرور را به فرمت قابل فهم برای جاوا اسکریپت (مانند JSON) تبدیل کنیم. دو روش اصلی برای این کار وجود دارد:

روش اول: استفاده از `.then()` و Promise

fetch('https://jsonplaceholder.typicode.com/posts/1')
  .then(response => {
    return response.json();
  })
  .then(data => {
    console.log('داده‌های دریافتی:', data);
  })
  .catch(error => {
    console.error('خطای شبکه:', error);
  });

روش دوم: استفاده از `async/await` (روش توصیه شده)

ساختار async/await خوانایی بسیار بالاتری دارد و کدهای ناهمگام را شبیه به کدهای همگام و خط به خط می‌سازد:

async function getPostData() {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('خطا در دریافت اطلاعات:', error);
  }
}

getPostData();

مدیریت خطاهای شبکه و status HTTP (نکته حیاتی)

مدیریت خطاهای شبکه و status HTTP (نکته حیاتی)

یکی از بزرگ‌ترین اشتباهات توسعه‌دهندگان هنگام استفاده از Fetch API این است که تصور می‌کنند خطاهای ۴۰۴ (Not Found) یا ۵۰۰ (Internal Server Error) به بلوک catch منتقل می‌شوند.

نکته بسیار مهم: تابع fetch() تنها زمانی Promise را Reject می‌کند (به catch می‌برد) که یک خطای واقعی در سطح شبکه مثل قطع بودن اینترنت یا عدم دسترسی به دامنه رخ دهد. اگر سرور پاسخی با کد وضعیت ۴۰۴ برگرداند، از نظر Fetch درخواست با موفقیت انجام شده است!

برای مدیریت درست خطاهای HTTP، باید همیشه ویژگی response.ok را چک کنید. این ویژگی فقط زمانی true است که status در بازه ۲۰۰ تا ۲۹۹ باشد:

async function fetchUser(userId) {
  try {
    const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);

    // بررسی کد وضعیت HTTP
    if (!response.ok) {
      throw new Error(`خطای HTTP! کد وضعیت: ${response.status}`);
    }

    const userData = await response.json();
    return userData;
  } catch (error) {
    console.error('عملیات ناموفق بود:', error.message);
  }
}

ارسال داده به سرور با متد POST

ارسال داده به سرور با متد POST

برای ارسال اطلاعات جدید به سرور (مثلاً ثبت‌نام کاربر یا ارسال فرم)، باید ورودی دوم fetch() را تنظیم کنید. این ورودی یک شیء تنظیمات (Options) است که شامل متد، هدرها و بدنه درخواست (body) می‌شود.

اگر قصد دارید با سرویس‌های بک‌اند یا ساختارهایی مانند سرویس‌های REST API در وردپرس ارتباط برقرار کنید، ارسال درست Content-Type الزامی است.

async function createNewPost() {
  const newPost = {
    title: 'آموزش Fetch API',
    body: 'این یک پست نمونه است.',
    userId: 1
  };

  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer YOUR_TOKEN_HERE'
      },
      body: JSON.stringify(newPost) // تبدیل شیء به رشته JSON
    });

    if (!response.ok) {
      throw new Error('خطا در ثبت اطلاعات');
    }

    const result = await response.json();
    console.log('پست با موفقیت ایجاد شد:', result);
  } catch (error) {
    console.error(error);
  }
}

متدهای PUT ،PATCH و DELETE

علاوه بر GET و POST، متدهای دیگری نیز در پروتکل HTTP برای ویرایش یا حذف داده‌ها استفاده می‌شوند:

  • PUT: جایگزین کردن کامل یک منبع با داده‌های جدید.
  • PATCH: بروزرسانی جزئی بخشی از یک منبع (مثلاً تغییر فقط آدرس ایمیل).
  • DELETE: حذف یک منبع مشخص از سرور.

مثال نحوه ارسال درخواست DELETE:

async function deletePost(postId) {
  try {
    const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${postId}`, {
      method: 'DELETE'
    });

    if (response.ok) {
      console.log(`پست شماره ${postId} با موفقیت حذف شد.`);
    }
  } catch (error) {
    console.error('خطا در حذف پست:', error);
  }
}

لغو درخواست‌ها و تعیین Timeout با AbortController

در برخی سناریوها مانند جستجوی هم‌زمان (Autocomplete) یا کندی اینترنت کاربر، نیاز داریم یک درخواست در حال ارسال را متوقف کنیم یا زمان مشخصی برای Timeout تعیین کنیم. برای این کار از کلاس بومی AbortController استفاده می‌شود.

async function fetchWithTimeout(url, timeoutMs = 5000) {
  const controller = new AbortController();
  const id = setTimeout(() => controller.abort(), timeoutMs);

  try {
    const response = await fetch(url, { signal: controller.signal });
    clearTimeout(id); // پاک‌سازی تایمر در صورت موفقیت
    const data = await response.json();
    return data;
  } catch (error) {
    if (error.name === 'AbortError') {
      console.error('درخواست به دلیل پایان مهلت زمانی (Timeout) لغو شد.');
    } else {
      console.error('خطای شبکه:', error);
    }
  }
}

// اگر پاسخ سرور بیشتر از ۳ ثانیه طول بکشد، لغو می‌شود
fetchWithTimeout('https://jsonplaceholder.typicode.com/photos', 3000);

ارسال فایل و داده‌های Form-Data

اگر فرمی دارید که شامل آپلود فایل (مانند تصویر یا PDF) است، نباید داده‌ها را به JSON تبدیل کنید. در عوض باید از شیء FormData استفاده شود.

اشتباه رایج: هنگام ارسال FormData، هرگز هدر Content-Type را به صورت دستی مقداردهی نکنید! مرورگر به‌صورت خودکار هدر را همراه با مرزهای (boundary) لازم برای فایل تنظیم می‌کند.
async function uploadUserAvatar(fileInput) {
  const formData = new FormData();
  formData.append('avatar', fileInput.files[0]);
  formData.append('username', 'ali_dev');

  try {
    const response = await fetch('/api/upload', {
      method: 'POST',
      body: formData // هدر Content-Type اتوماتیک تنظیم می‌شود
    });

    const result = await response.json();
    console.log('نتیجه آپلود:', result);
  } catch (error) {
    console.error('خطا در آپلود فایل:', error);
  }
}

عیب‌یابی سریع و رفع مشکلات رایج در Fetch API

  1. خطای CORS Error (Blocked by CORS policy):

    علت: مرورگر به دلیل قوانین امنیتی، اجازه دریافت اطلاعات از یک دامنه متفاوت را نمی‌دهد.

    حل مشکل: این مشکل باید در سمت سرور حل شود. سرور باید هدر Access-Control-Allow-Origin: * یا دامنه شما را تنظیم کند.
  2. خطای SyntaxError: Unexpected token in JSON at position 0:

    علت: متد response.json() فراخوانی شده اما پاسخ سرور فرمت JSON ندارد (مثلاً سرور صفحه ۴۰۴ HTML برگردانده یا پاسخ خالی است).

    حل مشکل: قبل از تبدیل به JSON، حتماً response.ok را چک کنید یا متن خروجی را با response.text() چاپ کنید تا جنس خروجی مشخص شود.
  3. عدم ارسال کوکی‌ها یا اطلاعات احراز هویت:

    علت: به‌صورت پیش‌فرض در درخواست‌های Cross-Site، کوکی‌ها ارسال نمی‌شوند.

    حل مشکل: مقدار credentials: 'include' را به شیء تنظیمات درخواست اضافه کنید.

پرسش‌های متداول

آیا برای استفاده از Fetch API نیاز به نصب فایل یا کتابخانه داریم؟

خیر، Fetch API به‌صورت داخلی و بومی در تمام مرورگرهای مدرن و نسخه‌های جدید Node.js پیاده‌سازی شده است و نیاز به هیچ ابزار خارجی ندارد.

تفاوت اصلی بین response.text() و response.json() چیست؟

متد response.json() خروجی دریافتی را به‌صورت اتوماتیک پارس کرده و به شیء جاوا اسکریپت تبدیل می‌کند، در حالی که response.text() خروجی خام سرور را به صورت یک رشته (String) ساده تحویل می‌دهد.

چرا کدهای درون catch هنگام دریافت خطاهای ۴۰۴ اجرا نمی‌شوند؟

چون کدهای HTTP از سمت سرور برگردانده شده‌اند و ارتباط شبکه قطع نشده است. برای تشخیص این خطاها باید ویژگی response.ok یا response.status چک شود.

آیا Fetch API از تمام مرورگرها پشتیبانی می‌کند؟

بله، تمامی مرورگرهای مدرن شامل Chrome، Firefox، Edge و Safari کاملاً از Fetch API پشتیبانی می‌کنند. تنها مرورگرهای بسیار قدیمی مثل Internet Explorer از آن پشتیبانی نمی‌کنند که نیازمند polyfill هستند.

سوالات متداول

چرا خطای ۴۰۴ یا ۵۰۰ در بلوک catch در Fetch API دریافت نمی‌شود؟

تابع fetch فقط در صورت بروز خطای واقعی شبکه (مانند قطع اینترنت) Promise را رد می‌کند. برای شناسایی کدهای وضعیت ۴۰۴ یا ۵۰۰ باید ویژگی response.ok را به‌صورت دستی بررسی کنید.

تفاوت اصلی Fetch API با کتابخانه Axios چیست؟

Fetch API ابزاری بومی در مرورگر است و نیازی به نصب ندارد، اما Axios امکاناتی مانند پارس خودکار JSON، مدیریت ساده‌تر خطاها و Interceptorها را به‌صورت پیش‌فرض ارائه می‌دهد.

چگونه داده‌ها را به فرمت JSON در Fetch ارسال کنیم؟

باید در هدر درخواست مقدار Content-Type را برابر application/json قرار داده و بدنه درخواست (body) را با تابع JSON.stringify به رشته تبدیل کنید.

چگونه یک درخواست Fetch را در صورت طولانی شدن لغو کنیم؟

برای لغو درخواست یا تنظیم Timeout می‌توانید از کلاس بومی AbortController استفاده کرده و سیگنال آن را به گزینه‌های درخواست fetch پاس دهید.

Table of Contents

آخرین نوشته‌ها

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *