مقدمه

تقریباً تمام اپلیکیشن‌های وب مدرن نیاز دارند تا با یک سرور برای دریافت یا ارسال داده ارتباط برقرار کنند. برای سال‌ها، این کار با استفاده از شیء XMLHttpRequest (XHR) انجام می‌شد که سینتکس پیچیده و غیرشهودی داشت. Fetch API جایگزین مدرن، قدرتمند و بسیار تمیزتر XHR است. این API یک رابط کاربری مبتنی بر Promise برای ارسال و دریافت درخواست‌های HTTP فراهم می‌کند و امروزه روش استاندارد برای انجام این کار در جاوااسکریپت محسوب می‌شود.

fetch یک تابع سراسری است که در window (برای اسکریپت‌های اصلی) و self (برای Web Workerها) در دسترس است و کار با منابع شبکه را بسیار ساده‌تر می‌کند.

ارسال یک درخواست ساده (GET)

ساده‌ترین کاربرد fetch، ارسال یک درخواست GET برای دریافت یک منبع است. این کار تنها با فراخوانی fetch و پاس دادن URL منبع مورد نظر انجام می‌شود. نکته کلیدی در کار با fetch، درک ماهیت دو-مرحله‌ای Promise آن است.

  1. Promise اول: متد fetch بلافاصله یک Promise برمی‌گرداند. این Promise به محض دریافت هدرهای (headers) پاسخ از سرور، resolve می‌شود. مقدار حل شده، خود داده‌ی نهایی نیست، بلکه یک شیء Response است که کل پاسخ HTTP را نمایندگی می‌کند.
  2. Promise دوم: برای دسترسی به بدنه‌ی اصلی پاسخ (body)، باید یکی از متدهای خواندن بدنه را روی شیء Response فراخوانی کنیم (مانند response.json() یا response.text()). این متدها نیز خودشان یک Promise برمی‌گردانند که پس از دانلود و پردازش کامل بدنه، با داده‌ی نهایی resolve می‌شود.
Copy Icon JAVASCRIPT
fetch('https://jsonplaceholder.typicode.com/posts/1')
    .then(response => {
        // Stage 1: Response object is received. We now need to parse the body.
        console.log('Received response object:', response);
        return response.json(); // This returns the second promise
    })
    .then(data => {
        // Stage 2: The body has been parsed into a JavaScript object.
        console.log('Final data:', data);
    })
    .catch(error => {
        // This block only catches network errors (e.g., no internet).
        console.error('Fetch Error:', error);
    });

این کد یک درخواست به یک API نمونه ارسال می‌کند. در اولین .then شیء Response را دریافت و متد .json() را برای خواندن بدنه فراخوانی می‌کنیم. در دومین .then به داده‌ی نهایی که یک شیء جاوااسکریپت است، دسترسی داریم.

شیء Response و مدیریت خطا

شیء Response حاوی اطلاعات مفیدی درباره پاسخ سرور است، مانند status (کد وضعیت HTTP مثل 200 یا 404)، statusText (پیام وضعیت مثل "OK" یا "Not Found") و پراپرتی بسیار مهم ok.

یک نکته بسیار مهم و یکی از تله‌های رایج در کار با fetch، نحوه مدیریت خطاهای HTTP است. Promise مربوط به fetch تنها در صورتی reject می‌شود که یک خطای شبکه‌ای رخ دهد (مانند عدم اتصال به اینترنت). اگر سرور با یک کد وضعیت خطا مانند 404 (Not Found) یا 500 (Internal Server Error) پاسخ دهد، از نظر fetch این یک تراکنش شبکه‌ای "موفق" است و Promise آن resolve می‌شود!

بنابراین، وظیفه ماست که به صورت دستی وضعیت پاسخ را بررسی کنیم. بهترین راه برای این کار، چک کردن پراپرتی response.ok است. این پراپرتی تنها برای کدهای وضعیت موفق (در محدوده 200 تا 299) برابر با true است. اگر false باشد، باید خودمان یک خطا throw کنیم تا توسط بلوک catch گرفته شود.

Copy Icon JAVASCRIPT
async function fetchData(url) {
    try {
        const response = await fetch(url);

        // The most important step: check if the HTTP response was successful
        if (!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status}`);
        }

        const data = await response.json();
        console.log('Successfully fetched data:', data);
    } catch (error) {
        // Catches both network errors and the manually thrown HTTP error
        console.error('Failed to fetch data:', error);
    }
}

// This will likely succeed
fetchData('https://jsonplaceholder.typicode.com/posts/1');

// This will likely fail with a 404, which our code will handle
fetchData('https://jsonplaceholder.typicode.com/posts/999999');

این نسخه با استفاده از async/await خواناتر است و الگوی صحیح مدیریت خطا را نشان می‌دهد. چک کردن response.ok و پرتاب کردن خطا در صورت ناموفق بودن پاسخ، یک الگوی استاندارد و ضروری در کار با Fetch API است.

در این درس با اصول اولیه Fetch API برای ارسال درخواست‌های GET و مدیریت پاسخ‌ها و خطاها آشنا شدیم. این مهارت برای دریافت داده از سرورها ضروری است. در درس بعدی، «الگوهای رایج Fetch»، به بررسی موارد پیشرفته‌تری مانند ارسال داده با درخواست‌های POST، تنظیم هدرها، و کار با داده‌های غیر-JSON خواهیم پرداخت.