آشنایی با Fetch API - بخش دوم
سایر خاصیتهای شئ Response
در بخش قبل با برخی خاصیتها و متدهای شئ Response آشنا شدیم. اما شئ Response دارای تعدادی خاصیت و متد دیگر نیز میباشد که در ادامه به معرفی ۳ مورد دیگر از خاصیتهای این شئ میپردازیم.
خاصیت type
پیش از این با مفهوم سیاست منبع یکسان یا Same-Origin Policy آشنا شدیم. و دیدیم که در صورت ارسال درخواستهای Ajax به آدرسهایی که در منبعی متفاوت قرار دارند، امکان دریافت پاسخ وجود ندارد. البته سرور میتواند با استفاده از هدرهای HTTP حالت پیشفرض را تغییر دهد. با استفاده از خاصیت type از شئ Response میتوان اطلاعاتی را در رابطه وضعیت پاسخ و سیاست SOP به دست آورد. این خاصیت میتواند یکی از مقادیر زیر را داشته باشد.
- basic : یعنی آدرس درخواست شده با آدرس صفحهی درخواست کننده در یک منبع قرار دارد.
- cors : یعنی آدرس درخواست شده با آدرس صفحهی درخواست کننده در یک منبع قرار ندارد. اما به دلیل غیر فعال بودن سیاست SOP، امکان استفاده از پاسخ دریافت شده وجود دارد.
- opaque : یعنی آدرس درخواست شده با آدرس صفحهی درخواست کننده در یک منبع قرار ندارد. و به دلیل فعال بودن سیاست SOP، امکان استفاده از پاسخ دریافت شده وجود ندارد.
- error : یعنی ارسال درخواست با خطا مواجه شده است و هیچ اطلاعات مفیدی دریافت نشده است. در این حالت مقدار خاصیت status برابر با صفر است.
قطعه کد زیر نحوهی استفاده از این خاصیت را نشان میدهد.
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then((response) => {
console.log(response.type);
});
← "cors"
این مثال را میتوانید اینجا اجرا کنید. با توجه به اینکه آدرس درخواست شده و آدرس صفحهی ارسال کنندهی درخواست در دو منبع متفاوت قرار دارند. با اجرای این مثال مقدار خاصیت type برابر با "cors" خواهد بود. (CORS مخفف Cross Origin Resource Sharing میباشد)
خاصیت redirected
حتماً تا به حال با صفحات وبی مواجه شدهاید که به صورت خودکار صفحهی وب دیگری را در مرورگر بارگذاری میکنند. این عمل تغییر مسیر یا Redirect نام دارد. در درخواستهای Ajax نیز ممکن است چنین اتفاقی رخ دهد. یعنی ممکن است شما آدرس خاصی را درخواست کنید. اما سرور شما را به آدرس دیگری منتقل کند. یا اصطلاحاً درخواست را Redirect کند. با استفاده از خاصیت redirected از شئ Response میتوان دریافت که درخواست ارسال شده Redirect شده است یا خیر؟
در صورتی که درخواست Ajax توسط سرور Redirect شده باشد. مقدار خاصیت redirected برابر با true خواهد بود. مثال زیر نحوهی استفاده از این خاصیت را نشان میدهد. این مثال را میتوانید اینجا اجرا کنید.
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then((response) => {
console.log(response.redirected);
});
← "false"
خاصیت headers
هدرهایی که توسط سرور در پاسخ HTTP قرار داده میشوند از طریق خاصیت headers قابل دسترسی هستند. در واقع خاصیت headers یک نمونه از شئ Headers میباشد. این شئ دارای تعدادی متد است که با استفاده از آنها امکان دسترسی به هدرهای ذخیره شده در این شئ، و همچنین اضافه کردن هدرهای جدید وجود دارد. مهمترین متدهای شئ Headers در لیست زیر به همراه کاربردشان نشان داده شدهاند.
- get(name) : در صورتی که هدر name وجود داشته باشد مقدار آن را بازمیگرداند. در غیر این صورت مقدار null را بازمیگرداند.
- set(name , value) : در صورتی که هدر name وجود داشته باشد مقدار آن را به value تغییر میدهد. در غیر این صورت هدر name را با مقدار value ایجاد میکند.
- delete(name) : در صورتی که هدر name وجود داشته باشد آن را حذف میکند.
- append(name , value) : در صورتی که هدر name وجود داشته باشد مقدار value را به مقدار قبلی الحاق میکند. در غیر این صورت هدر name را با مقدار value ایجاد میکند.
- has(name) : در صورتی که هدر name وجود داشته باشد مقدار true را بازمیگرداند. در غیر این صورت مقدار false را بازمیگرداند.
مثال زیر نحوهی استفاده از خاصیت headers در پاسخهای دریافت شده از سرور را نشان میدهد.
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then((response) => {
console.log(response.headers.get('Content-Type')); // "application/json; charset=utf-8"
console.log(response.headers.get('Date')); // null
console.log(response.headers.has('Content-Type')); // true
console.log(response.headers.has('Date')); // false
});
در این مثال فرض شده است که هدر "Content-Type" در پاسخ دریافت شده از سرور وجود دارد. و هدر "Date" در پاسخ دریافت شده وجود ندارد. بنابراین متد get برای هدر "Date" مقدار null را بازمیگرداند. همچنین متد has برای این هدر مقدار false را بازمیگرداند. این مثال را میتوانید اینجا اجرا کنید.
ارسال درخواستهای پیشرفته با Fetch API
تمام درخواستهایی که در مثالهای قبلی با استفاده از تابع fetch ارسال کردیم، درخواستهای بسیار سادهای بودند. یعنی تمام درخواستها با تنظیمات پیشفرض ارسال میشدند. هرچند در بسیاری از موارد همین تنظیمات پیشفرض پاسخگوی نیازهای ما هستند. اما در برخی شرایط لازم است تا تنظیمات پیشفرض را تغییر دهیم و درخواستها را با تنظیمات سفارشی ارسال کنیم.
به عنوان مثال در حالت پیشفرض تمام درخواستها با روش GET ارسال میشوند. اما ممکن است بخواهیم درخواستی را با روش POST ارسال کنیم. همچنین در حالت پیشفرض تمام هدرهای HTTP توسط مرورگر تنظیم میشوند. اما ممکن است بخواهیم هدرهای دیگری را به درخواست HTTP اضافه کنیم و یا تغییراتی در هدرهای موجود ایجاد کنیم.
برای ارسال درخواستهای پیشرفته با استفاده از Fetch API، باید از شئ Request استفاده کنیم. با استفاده از این شئ میتوان یک درخواست HTTP را با تنظیمات دلخواه ایجاد کرد. سپس با ارسال شئ ایجاد شده به تابع fetch میتوان درخواست مورد نظر را به سرور ارسال کرد. قطعه کد زیر یک مثال ساده از نحوهی ایجاد و ارسال یک درخواست HTTP با استفاده از شئ Request را نشان میدهد.
const req = new Request('https://example.com' , {
method: 'POST',
mode: 'cors',
redirect: 'follow'
});
fetch(req)
.then((response) => {
// دستورات مربوط به مدیریت پاسخ
})
.catch((error) => {
// دستورات مربوط به مدیریت خطا
});
مشاهده میکنید که تابع سازندهی شئ Request دو آرگومان ورودی دریافت میکند. آرگومان اول آدرس URL درخواست است که ارسال این آرگومان اجباری است. و آرگومان دوم شیئی است که سایر تنظیمات درخواست، با خاصیتهای این شئ تعیین میشوند. البته ارسال این آرگومان اختیاری است. پس از ایجاد یک شئ از نوع Request، جهت ارسال درخواست باید شئ ایجاد شده را به تابع fetch ارسال میکنیم. بقیهی مراحل مربوط به مدیریت پاسخ و خطاها مشابه قبل است.
در آرگومان دوم تابع Request، میتوان تنظیمات زیادی را انجام داد که لیست کامل این تنظیمات را اینجا میتوانید مشاهده کنید. در ادامه مهمترین تنظیمات مورد استفاده در این آرگومان را معرفی میکنیم.
خاصیت method
روش ارسال درخواست را تعیین میکند. (معمولاً GET یا POST)
خاصیت headers
یک شئ از نوع Headers است که هدرهای ارسال شونده به سرور را تعیین میکند.
خاصیت body
بدنهی درخواست در این خاصیت تعیین میشود. مقدار این خاصیت میتواند یک رشتهی ساده، یک رشتهی JSON، یک شئ FormData و ... باشد.
خاصیت cache
حتماً میدانید که مرورگرها دارای بخشی به نام حافظهی کش (Cache) هستند. بسیاری از منابعی که توسط یک مرورگر دریافت میشوند (مانند صفحات وب، فایلهای CSS یا فایلهای PNG) در این حافظه ذخیره میشوند. مرورگرها در حالت پیشفرض قبل از ارسال یک درخواست HTTP برای دریافت یک منبع، معمولاً حافظهی کش را بررسی میکنند. در صورتی که منبع مورد نظر از قبل در حافظهی کش ذخیره شده باشد و تاریخ انقضای آن نیز نگذشته باشد. مرورگر از همان نسخهی ذخیره شده استفاده میکند و عملاً هیچ درخواستی به سرور ارسال نمیشود.
هرچند این مکانیزم باعث افزایش سرعت اجرای درخواستها میشود، اما در برخی موارد ممکن است مشکلاتی را نیز به وجود بیاورد. در چنین شرایطی لازم است تا به مرورگر اطلاع دهیم که از حافظهی کش به چه نحوی استفاده شود. با استفاده از خاصیت cache در آرگومان دوم تابع Request، میتوان نحوهی عملکرد مرورگر را در رابطه با حافظهی کش کنترل کرد. این خاصیت میتواند مقادیر مختلفی داشته باشد که مهمترین موارد به شرح زیر میباشند.
- default : مرورگر رفتار پیشفرض خود را انجام میدهد. یعنی در صورت وجود منبع مورد نظر در حافظهی کش و عدم انقضای آن، از حافظهی کش استفاده میکند.
- no-store : مرورگر از حافظهی کش استفاده نمیکند. و پس از دریافت منبع مورد نظر، حافظهی کش را به روز نمیکند. یعنی منبع دریافت شده را در حافظهی کش ذخیره نمیکند.
- reload : مرورگر از حافظهی کش استفاده نمیکند. اما پس از دریافت منبع مورد نظر، آن را در حافظهی کش ذخیره میکند.
- no-cache : ابتدا حافظهی کش بررسی میشود. اگر منبع مورد نظر وجود نداشت، درخواستی برای دریافت آن ارسال میشود. اما اگر منبع مورد نظر در حافظهی کش وجود داشت، بدون توجه به تاریخ انقضای آن، یک درخواست به سرور ارسال شده و بررسی میشود که نسخهی موجود در سرور با نسخهی موجود در حافظهی کش مغایرتی دارد یا خیر؟ در صورتی که مغایرتی وجود نداشته باشد، از حافظهی کش استفاده میشود. در غیر این صورت منبع مورد نظر به طور کامل از سرور دریافت میشود.
خاصیت mode
در حالت پیشفرض امکان ارسال درخواستهای Ajax به هر منبعی وجود دارد. هرچند پس از دریافت پاسخ، فقط در دو حالت میتوان از پاسخ دریافت شده استفاده کرد. یا باید منبع صفحهی ارسال کننده با منبع درخواست شده یکسان باشد (سیاست SOP). یا اینکه سیاست SOP توسط سرور غیر فعال شده باشد. یعنی سیاست SOP پس از دریافت پاسخ از سرور اعمال میشود و در ارسال درخواست نقشی ندارد.
اما با استفاده از خاصیت mode میتوان در ارسال درخواستهای Ajax نیز محدودیت ایجاد کرد. مقدار این خاصیت در حالت پیشفرض برابر با "cors" است. یعنی امکان ارسال درخواست به هر منبعی وجود دارد. اما با تغییر مقدار این خاصیت به "same-origin" امکان ارسال درخواست به آدرسهایی که در منبعی متفاوت قرار دارند لغو میشود. در این حالت حتی اگر سیاست SOP از طرف سرور غیر فعال شده باشد. باز هم امکان ارسال درخواست به منابع دیگر وجود ندارد.
خاصیت credentials
با استفاده از این خاصیت میتوان نحوهی ارسال کوکیها در درخواستهای Ajax را تعیین کرد. این خاصیت میتواند یکی از ۳ مقدار زیر را داشته باشد.
- omit : به طور کامل از ارسال کوکیها جلوگیری میکند.
- same-origin : تنها در صورتی که منبع آدرس درخواست شده با منبع صفحهی جاری یکسان باشد کوکیها ارسال میشوند. (این حالت پیشفرض است)
- include : بدون در نظر گرفتن منبع، کوکیها ارسال میشوند.
مثال زیر نحوهی ارسال یک فرم را با روش POST نشان میدهد. توجه کنید که در این مثال فرض شده است که یک فرم در صفحهی وب وجود دارد که مقدار صفت id آن برابر با "my-form" است. همچنین برای خواندن مقادیر وارد شده در این فرم و ارسال آنها، از یک شئ FormData استفاده شده است.
const form = document.getElementById('my-form');
const data = new FormData(form);
const h = new Headers({
'Cache-Control': 'no-store',
'From': 'abbassac@gmail.com'
});
const req = new Request('https://example.com', {
method: 'POST',
headers: h,
body: data
});
fetch(req);
// Handle the response
به نحوهی استفاده از تابع سازندهی شئ Headers توجه کنید. در این مثال هدرهای HTTP با ارسال یک شئ به تابع Headers ایجاد شدهاند. هرچند با استفاده از متدهای append یا set نیز میتوان هدرهای جدیدی به این شئ اضافه کرد. همچنین به نحوهی استفاده از شئ FormData توجه کنید. ابتدا با استفاده از فرم موجود در صفحهی وب یک شئ FormData ایجاد شده است. سپس این شئ به عنوان بدنهی درخواست در خاصیت body قرار گرفته است. همچنین برای ارسال هدرهای HTTP، شئ h در خاصیت headers قرار گرفته است. در نهایت هم شئ req به تابع fetch ارسال شده است. در خطوط بعدی نیز میتوان پاسخ دریافت شده را مانند مثالهای قبل مدیریت کرد.