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

fetch() API در شی پنجره فرود می آید و به دنبال جایگزینی XHR ها است

XMLHttpRequest بسیار طولانی است

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

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

  • 42
  • 14
  • 39
  • 10.1

منبع

Fetch API از Chrome 40 در محدوده جهانی Service Worker در دسترس بوده است، اما در Chrome 42 در محدوده پنجره فعال خواهد شد. همچنین یک polyfill نسبتاً واکشی توسط GitHub وجود دارد که می توانید امروز از آن استفاده کنید.

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

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

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

XMLHttpRequest

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

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

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

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

رفتن و آوردن

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

fetch('./api/some.json')
    .then(
    function(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(function(err) {
    console.log('Fetch Error :-S', err);
    });

قبل از تجزیه پاسخ به عنوان JSON، بررسی می کنیم که وضعیت پاسخ 200 باشد.

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

فراداده پاسخ

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

fetch('users.json').then(function(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 تقریباً یکسان هستند به جز اینکه پاسخ cors سرصفحه‌هایی را که می‌توانید مشاهده کنید به 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(function(response) {
    return response.text();
    })
    .then(function(text) {
    console.log('Request successful', text);
    })
    .catch(function(error) {
    log('Request failed', error)
    });

وعده های زنجیره ای

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

اگر با یک 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(function(data) {
    console.log('Request succeeded with JSON response', data);
    }).catch(function(error) {
    console.log('Request failed', error);
    });

ما تابع status را تعریف می کنیم که پاسخ.status را بررسی می کند و نتیجه Promise.resolve() یا Promise.reject() را برمی گرداند که یک Promise حل شده یا رد شده را برمی گرداند. این اولین روشی است که در زنجیره fetch() ما فراخوانی می شود، اگر حل شود، متد 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(function (data) {
    console.log('Request succeeded with JSON response', data);
    })
    .catch(function (error) {
    console.log('Request failed', error);
    });

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

اگر می‌خواهید با اعتبارنامه‌هایی مانند کوکی‌ها درخواست واکشی کنید، باید credentials درخواست را روی "include" تنظیم کنید.

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

سوالات متداول

چگونه درخواست fetch() را لغو کنم؟

در حال حاضر راهی برای لغو واکشی وجود ندارد، اما این موضوع در GitHub مورد بحث قرار گرفته است. H/T @jaffathecake برای این لینک.

پلی فیل وجود دارد؟

GitHub دارای یک polyfill برای واکشی است . H/T @Nexii برای اشاره به این موضوع.

چرا "no-cors" در سرویس کارگران پشتیبانی می شود اما از پنجره پشتیبانی نمی شود؟

این به دلیل یک نگرانی امنیتی است، می توانید در اینجا اطلاعات بیشتری کسب کنید .