مقدمه ای برای fetch()

fetch() به شما امکان می دهد درخواست های شبکه ای مشابه XMLHttpRequest (XHR) انجام دهید. تفاوت اصلی این است که Fetch API از Promises استفاده می کند، که یک API ساده تر دارد تا به شما کمک کند از تماس های پیچیده در XMLHttpRequest API اجتناب کنید.

پشتیبانی مرورگر

  • کروم: 42.
  • لبه: 14.
  • فایرفاکس: 39.
  • سافاری: 10.1.

منبع

اگر قبلاً از Promises استفاده نکرده‌اید، مقدمه JavaScript Promises را بررسی کنید.

درخواست اولیه واکشی

در اینجا مثالی است که با یک XMLHttpRequest و سپس با fetch پیاده سازی شده است. ما می خواهیم یک URL درخواست کنیم، یک پاسخ دریافت کنیم و آن را به عنوان JSON تجزیه کنیم.

XMLHttpRequest

یک XMLHttpRequest به دو شنونده برای رسیدگی به موارد موفقیت و خطا و یک فراخوان برای open() و send() نیاز دارد. نمونه ای از اسناد MDN .

function reqListener () {
  const data = JSON.parse(this.responseText);
  console.log(data);
}

function reqError (err) {
  console.log('Fetch Error :-S', err);
}

const oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();

واکشی

درخواست واکشی ما به این صورت است:

fetch('./api/some.json')
  .then(response => {
    if (response.status !== 200) {
      console.log(`Looks like there was a problem. Status Code: ${response.status}`);

      return;
    }

    // Examine the text in the response
    response.json().then(function(data) {
      console.log(data);
    });
  })
  .catch(err => {
    console.log('Fetch Error :-S', err);
  });

درخواست fetch() فقط به یک فراخوانی نیاز دارد تا کار مشابه XHR را انجام دهد. برای پردازش پاسخ، ابتدا بررسی می کنیم که وضعیت پاسخ 200 باشد، سپس پاسخ را به صورت JSON تجزیه می کنیم. پاسخ به درخواست fetch() یک شی Stream است، به این معنی که پس از فراخوانی متد json() یک Promise برگردانده می شود. جریان به صورت ناهمزمان رخ می دهد.

فراداده پاسخ

مثال قبلی وضعیت شی Response و نحوه تجزیه پاسخ را به صورت JSON نشان داد. در اینجا نحوه مدیریت سایر ابرداده هایی که ممکن است بخواهید به آنها دسترسی داشته باشید، مانند هدرها آورده شده است:

fetch('users.json').then(response => {
  console.log(response.headers.get('Content-Type'));
  console.log(response.headers.get('Date'));

  console.log(response.status);
  console.log(response.statusText);
  console.log(response.type);
  console.log(response.url);
});

انواع پاسخ

وقتی یک درخواست واکشی می‌کنیم، به پاسخ response.type از نوع " basic "، " cors " یا " opaque " داده می‌شود. این types نشان می دهد که منبع از کجا آمده است، و شما می توانید از آنها برای تعیین نحوه برخورد با شی پاسخ استفاده کنید.

هنگامی که مرورگر منبعی را در همان مبدأ درخواست می کند، پاسخ دارای یک نوع basic با محدودیت هایی است که می توانید از پاسخ مشاهده کنید.

اگر درخواستی برای منبعی در مبدأ دیگر انجام شود و آن مبدا سرصفحه های COR را برمی گرداند، آنگاه نوع آن cors است. پاسخ‌های cors مشابه پاسخ‌های basic هستند، اما هدرهایی را که می‌توانید مشاهده کنید به Cache-Control ، Content-Language ، Content-Type ، Expires ، Last-Modified و Pragma محدود می‌کنند.

پاسخ‌های opaque از منشأ متفاوتی می‌آیند که سرصفحه‌های CORS را بر نمی‌گرداند. با یک پاسخ غیر شفاف، نمی‌توانیم داده‌های بازگردانده شده را بخوانیم یا وضعیت درخواست را مشاهده کنیم، به این معنی که نمی‌توانید بررسی کنید که آیا درخواست موفق بوده است یا خیر.

شما می توانید حالتی را برای درخواست واکشی تعریف کنید تا فقط انواع خاصی از درخواست ها حل شوند. حالت هایی که می توانید تنظیم کنید به شرح زیر است:

  • same-origin فقط برای درخواست‌های دارایی‌هایی در همان مبدا موفق می‌شود و همه درخواست‌های دیگر را رد می‌کند.
  • cors به ​​درخواست‌هایی برای دارایی‌ها در همان مبدا و سایر مبداها اجازه می‌دهد که هدرهای COR مناسب را برمی‌گردانند.
  • cors-with-forced-preflight قبل از هر درخواستی یک بررسی قبل از پرواز انجام می دهد.
  • no-cors در نظر گرفته شده است که درخواست‌هایی را به مبداهای دیگری ارسال کند که سرصفحه CORS ندارند و منجر به پاسخ opaque می‌شوند، اما همانطور که گفته شد، در حال حاضر در محدوده کلی پنجره این امکان وجود ندارد.

برای تعریف حالت، یک شی گزینه به عنوان پارامتر دوم در درخواست fetch اضافه کنید و حالت را در آن شی تعریف کنید:

fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
  .then(response => response.text())
  .then(text => {
    console.log('Request successful', text);
  })
  .catch(error => {
    log('Request failed', error)
  });

زنجیر زنی

یکی از ویژگی های عالی وعده ها، توانایی زنجیر کردن آنها به یکدیگر است. برای fetch() ، این به شما امکان می دهد منطق را در بین درخواست های واکشی به اشتراک بگذارید.

اگر با یک API JSON کار می کنید، باید وضعیت را بررسی کنید و JSON را برای هر پاسخ تجزیه کنید. می‌توانید کد خود را با تعریف وضعیت و تجزیه JSON در توابع جداگانه‌ای که وعده‌ها را برمی‌گردانند ساده کنید و از درخواست واکشی فقط برای رسیدگی به داده‌های نهایی و مورد خطا استفاده کنید.

function status (response) {
  if (response.status >= 200 && response.status < 300) {
    return Promise.resolve(response)
  } else {
    return Promise.reject(new Error(response.statusText))
  }
}

function json (response) {
  return response.json()
}

fetch('users.json')
  .then(status)
  .then(json)
  .then(data => {
    console.log('Request succeeded with JSON response', data);
  }).catch(error => {
    console.log('Request failed', error);
  });

این مثال یک تابع status را تعریف می کند که response.status را بررسی می کند و یک Promise حل شده را به عنوان Promise.resolve() یا یک Promise رد شده را به عنوان Promise.reject() برمی گرداند. این اولین روشی است که در زنجیره fetch() نامیده می شود.

اگر Promise حل شود، اسکریپت متد json() را فراخوانی می کند، که Promise دوم را از فراخوانی response.json() برمی گرداند و یک شی حاوی JSON تجزیه شده ایجاد می کند. اگر تجزیه ناموفق باشد، Promise رد می شود و دستور catch اجرا می شود.

این ساختار به شما امکان می‌دهد منطق را در تمام درخواست‌های واکشی خود به اشتراک بگذارید و نگهداری، خواندن و آزمایش کد را آسان‌تر می‌کند.

درخواست ارسال

گاهی اوقات یک برنامه وب باید یک API را با روش POST فراخوانی کند و برخی پارامترها را در متن درخواست قرار دهد. برای انجام این کار، پارامترهای method و body را در گزینه‌های fetch() تنظیم کنید:

fetch(url, {
    method: 'post',
    headers: {
      "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
    },
    body: 'foo=bar&lorem=ipsum'
  })
  .then(json)
  .then(data => {
    console.log('Request succeeded with JSON response', data);
  })
  .catch(error => {
    console.log('Request failed', error);
  });

اعتبارنامه را با درخواست واکشی ارسال کنید

برای ایجاد یک درخواست واکشی با اعتبارنامه هایی مانند کوکی ها، مقدار credentials درخواست را روی "include" تنظیم کنید:

fetch(url, {
  credentials: 'include'
})