بررسی تابع fetch در جاوااسکریپت

سلام دوستان جاوااسکریپتی! اگه تا الان با پلاگین‌ها و کتابخونه‌های خارجی مثلا جی‌کوئری و Axios برای ارسال درخواست ای‌جکس (Ajax) کار می‌کردیم، خوبه که بدونیم جاوااسکریپت برای این کار یک تابع درونی به اسم fetch اضافه کرده که علاوه بر قدرتمند بودن، کار با اون خیلی راحت و ساده هست. امروز این تابع رو بررسی می‌کنیم.

نکته: برای درک بهتر این تابع، باید با پرامیس‌های جاوااسکریپت آشنایی داشته باشین. همچنین توی این پست برای سادگی و خوانایی بهتر از async/await استفاده شده. اگه با این موضوع‌ها آشنایی ندارین می‌تونین پست‌های زیر رو بخونین:



تابع fetch

کار با این تابع به سادگی کد زیر هست:

fetch(url);

تموم! این تابع بعد از اجرا شدن، یک پرامیس به ما برمی‌گردونه. این پرامیس شامل یک سری اطلاعات از نتیجه درخواست هست. برای اینکه به این اطلاعات دسترسی داشته باشیم باید پرامیس رو باز کنیم. ابتدا کارمون رو با مثال زیر شروع کنیم:

async function users() {
  let response = await fetch('https://randomuser.me/api/?results=10');
  
  console.log(response);
};

users();

خروجی خط ۴ بصورت زیر هست:

همونطور که می‌بینیم خروجی یک نمونه از کلاس داخلی Response که شامل اطلاعاتی مثل status و headers و body هست. چیزی که توی body قرار گرفته، شامل پاسخ اصلی هست که از سمت سرور اومده. توی این مرحله باید مشخص کنیم پاسخی که از سرور اومده رو به چه فرمتی می‌خوایم؛ متنی؟ جی‌سان؟ ?


توی شرایط مختلف می‌تونیم از فرمت‌های زیر استفاده کنیم:

response.text();
response.json();
response.formData();
response.blob();
response.arrayBuffer();

خروجی همه‌ی فرمت‌های بالا یک پرامیس هست. پس برای دسترسی به خروجی اصلی باید یه بار دیگه پرامیس رو پردازش کنیم.


توی مثالمون می‌خوایم خروجی جی‌سان باشه. پس از خط ۲ کد بالا استفاده می‌کنیم. کد رو بصورت زیر تکمیل کنیم:

async function users() {
  let response = await fetch('https://randomuser.me/api/?results=10');
  let data = await response.json();

  return data;
};

users().then(data => console.log(data));

به همین سادگی. خط ۸ کد بالا شامل پاسخی هست که از سرور اومده و به صورت جی‌سان خواهد بود.

در حالت پیشفرض درخواست‌ها با متد GET فرستاده میشن. برای مشخص کردن متد و یا تنظیم کردن هدر باید درخواستمون رو شخصی‌سازی کنیم.




شخصی‌سازی درخواست

توی پارامتر دوم تابع fetch می‌تونیم نوع متد رو مشخص کنیم، data پاس بدیم و هدر ست کنیم:

const request = fetch(url, {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    Authorization: 'Bearer ...'
  },
  body: JSON.stringify({ name: 'Warner' })
});


request
.then(response => response.json())
.then(result => {
  console.log(result);
});

توی مثال بالا متد رو method مشخص کردیم. برای ارسال هدر درخواست از headers استفاده کردیم و برای ارسال اطلاعات به سرور از body. نوع body ‌‌می‌تونه رشته‌‌ای یا Blob باشه. و یا FormData مثل کد زیر:

let formData = new FormData();
formData.append('name', 'Duck');
formData.append('lastname', 'Ducky');

let request = fetch(url, {
  method: 'POST',
  body: formData
});



مدیریت خطاها

خب می‌دونیم که همیشه درخواست‌ها موفقیت آمیز نیستن و ممکنه خطاهایی مثل ۴۰۴، ۴۰۱ پیش بیاد و یا کلا سرور یا اینترنت در دسترس نباشن. اگه درخواستی موفقیت آمیز نباشه، خروجی تابع fetch بصورت زیر هست:

همونطور که می‌بینیم status داره کد ۴۰۴ رو نشون میده و مقدار ok برابر با false هست. برای اینکه بتونیم این خطا رو مدیریت کنیم، کد رو به صورت زیر می‌نویسیم:

async function users() {
  try {
    let response = await fetch('https://randomuser.me/apis/?results=10');
  
    if (response.ok) {
      let data = await response.json();
      return data;
    }
  } catch(e) {
    // Handle the unexpected error
  }
};

users().then(data => {
  if (typeof data == 'object') {
    // ...
  }
});

توی این مثال و توی خط ۵ از response.ok استفاده کردیم که مقدار اون اگه نتیجه درخواست موفقیت آمیز باشه true هست. همچنین از try/catch استفاده کردیم که اگه با خروجی غیرمنتظره‌ای (مثل CORS) مواجه شدیم بتونیم اون رو مدیریت کنیم.



نتیجه گیری

همونطور که می‌بینیم تابع fetch برای استفاده‌های ساده، خیلی مفید و راحت هست که وقتی با async/await مخلوط میشه جذاب‌تر هم میشه. اما انعطاف پذیری‌هایی که توی پلاگین‌های بیرونی وجود داره رو هنوز توی این تابع نمی‌بینیم. مثل مشخص کردن یک هدر پیشفرض که توی همه‌ی درخواست‌ها ست شده باشه و یا مدیریت راحت‌تر خطاها. همچنین این تابع فقط توی محیط مرورگرهای مدرن قابل استفاده هست. (وضعیت پشتیبانی مرورگرها از این تابع رو ببینید).

البته برای همه‌ی این کاستی‌ها راه حل هم وجود داره. برای استفاده از این تابع توی مرورگرهای قدیمی میشه از پلاگین‌هایی استفاده کنیم که این تابع رو Polyfill کردن. همچنین پلاگین‌هایی مثل zlFetch وجود داره که زیر پوست از fetch استفاده می‌کنه که با اون میشه خروجی (موفقیت‌آمیز بودن یا خطا) رو بهتر مدیریت کرد.




خب این مقاله هم به پایان رسید. روزتون خوش ? ?

منابعی که برای این پست استفاده کردم:

https://javascript.info/fetch

https://medium.com/javascrip...

https://css-tricks.com/using-fetch/

https://ditty.ir/