بررسی دقیق‌تر شیء Response و کار عملی با JSON

در درس قبل با ساختار کلی fetch و استخراج داده با متد json() آشنا شدید. در این درس، نگاهی دقیق‌تر به خود شیء Response می‌اندازیم: چه اطلاعاتی در آن وجود دارد، چگونه می‌توان هدرهای پاسخ را خواند، و چند نکته‌ی مهم درباره‌ی رفتار واقعی JSON در تعامل با سرور که در پروژه‌های واقعی اغلب باعث اشتباه می‌شوند.

ویژگی‌های کلیدی شیء Response

شیء Response که از fetch برگردانده می‌شود، فقط بدنه‌ی پاسخ را در خود ندارد، بلکه اطلاعات کاملی درباره‌ی خود پاسخ HTTP ارائه می‌دهد:

ویژگی توضیح
response.status کد وضعیت عددی پاسخ، مثل 200 یا 404
response.statusText عبارت متنی مرتبط با کد وضعیت، مثل "Not Found"
response.ok مقدار boolean؛ true اگر status بین 200 تا 299 باشد
response.headers شیء Headers شامل تمام هدرهای پاسخ سرور
response.url آدرس نهایی درخواست، حتی پس از ریدایرکت

خواندن هدرهای پاسخ

هدرهای پاسخ از طریق شیء Headers در دسترس هستند که متد get را برای خواندن مقدار یک هدر مشخص ارائه می‌دهد:

fetch("https://api.example.com/products")
  .then((response) => {
    console.log(response.headers.get("Content-Type"));
    // مثلاً "application/json; charset=utf-8"
    return response.json();
  });

نکته‌ی مهم: بدنه‌ی پاسخ فقط یک‌بار قابل خواندن است

یکی از رفتارهای غیرمنتظره برای بسیاری از توسعه‌دهندگان تازه‌کار این است که بدنه‌ی یک شیء Response فقط یک‌بار قابل مصرف است. فراخوانی دوباره‌ی json() یا text() روی همان پاسخ، خطا ایجاد می‌کند:

fetch("https://api.example.com/products").then(async (response) => {
  const data1 = await response.json();
  const data2 = await response.json(); // خطا: body stream already read
});

اگر نیاز باشد از یک پاسخ چند‌بار استفاده شود، باید پیش از خواندن بدنه، از متد response.clone() استفاده کرد که یک نسخه‌ی مستقل از پاسخ ایجاد می‌کند.

مدیریت خطای JSON نامعتبر

گاهی سرور به‌جای JSON معتبر، پاسخی مثل صفحه‌ی خطای HTML یا رشته‌ی خالی برمی‌گرداند. در این حالت، خود متد json() خطا می‌دهد و این خطا باید در بلوک catch مدیریت شود:

مدیریت خطای تبدیل JSON
خروجی کنسول اینجا نمایش داده می‌شود...

JSON.stringify و JSON.parse به‌عنوان پایه‌ی کار با JSON

پیش از ادامه، یادآوری دو متد پایه‌ای که در درس‌های قبل نیز دیده‌اید ضروری است، چون اساس تبدیل داده در ارتباط با سرور هستند:

const product = { id: 1, name: "کتاب", price: 120000 };

const jsonString = JSON.stringify(product);
console.log(jsonString); // '{"id":1,"name":"کتاب","price":120000}'

const parsedBack = JSON.parse(jsonString);
console.log(parsedBack.name); // "کتاب"

response.json() در واقع همان کاری را که JSON.parse روی یک رشته انجام می‌دهد، به‌صورت خودکار روی بدنه‌ی پاسخ اجرا می‌کند؛ با این تفاوت که خودش هم یک عملیات ناهمزمان (asynchronous) است و به همین دلیل Promise برمی‌گرداند.

نکات کلیدی

  • شیء Response شامل اطلاعاتی فراتر از بدنه‌ی پاسخ است، از جمله status، headers و url.
  • بدنه‌ی هر Response فقط یک‌بار قابل خواندن است؛ برای استفاده‌ی چندباره باید از response.clone() استفاده کرد.
  • اگر پاسخ سرور JSON معتبر نباشد، خود متد json() خطا تولید می‌کند که باید در catch مدیریت شود.
  • response.json() معادل خودکار و ناهمزمان JSON.parse روی بدنه‌ی پاسخ سرور است.

جمع‌بندی

شناخت دقیق شیء Response، فراتر از فراخوانی ساده‌ی json()، برای مدیریت درست خطاها و اطلاعات پاسخ سرور ضروری است. نکاتی مثل یک‌بار‌مصرف بودن بدنه‌ی پاسخ و لزوم بررسی معتبر بودن JSON، از جمله مواردی هستند که در پروژه‌های واقعی بارها باعث باگ‌های پنهان می‌شوند. در درس بعدی، نحوه‌ی ارسال داده به سرور با متد POST و تنظیم بدنه و هدرهای درخواست بررسی خواهد شد.