جاوا اسکریپت Async: آشنایی با Fetch API

جاوا اسکریپت Async: آشنایی با Fetch API

آشنایی با Fetch API

تا این قسمت توانسته ایم با AJAX و شیء XMLHttpRequest کار کنیم و تمامی موارد آن را یاد بگیریم اما بحث شیء XMLHttpRequest قدیمی است و در حال حاضر روش جدیدی به نام Fetch API برای کار با درخواست های HTTP وجود دارد. برای شروع این جلسه ابتدا باید 4 فایل زیر را ایجاد کنید:

  • index.html
  • app.js
  • text.txt
  • posts.json

من محتویات فایل HTML را برایتان آماده کرده ام تا با هم تمرین را شروع کنیم:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.css" />
  <title>Ajax Sandbox</title>
</head>
<body>
  <div class="container">
    <h1>Fetch API Sandbox</h1>
    <button id="button1">Get Text</button> 
    <button id="button2">Get JSON</button>
    <button id="button3">Get API Data</button>
    <br><br>
    <div id="output"></div>
  </div>

  <script src="app.js"></script>
</body>
</html>

div خالی که مشاهده می کنید برای هدف گیری با جاوا اسکریپت و نوشتن نتیجه ی درخواست ها است و فعلا آن را خالی می گذاریم. همانطور که می بینید این فایل یک صفحه ی ساده ی وب است که از skeleton استفاده می کند. در پروژه ی روبروی شما سه دکمه وجود دارد که یکی برای دریافت متن از یک فایل متنی و دیگری دریافت JSON از یک فایل JSON و سومی برای دریافت داده از یک API خارجی است.

برای محتویات فایل txt می توانید یک متن ساده بنویسید. مثلا من متن This is a sample text file را درون آن قرار داده ام. حالا به فایل app.js بروید تا دکمه ی اول را هدف بگیریم. مثل همیشه باید از یک event-listener استفاده کنیم:

document.getElementById('button1').addEventListener('click', getText);

تابع getText هنوز وجود ندارد بنابراین باید آن را تعریف کنیم:

// Get local text file data
function getText() {

}

در قدم اول برای استفاده از Fetch API باید کلمه ی fetch را تایپ کنیم و سپس به عنوان پارامتر نام فایل خود را به آن پاس می دهیم. در مرحله ی بعد باید از promise ها استفاده کنیم. اگر یادتان باشد در جلسه ی قبل به شما گفتم که برای دریافت پاسخ درخواست از طریق promise ها از تابع then استفاده می کنیم بنابراین:

// Get local text file data
function getText() {
    fetch('test.txt')
        .then();
}

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

// Get local text file data
function getText() {
    fetch('test.txt')
        .then(function (res) {
            console.log(res);
        });
}

برای تست یک console.log از پاسخ گرفته ام که باعث دریافت پیام زیر در کنسول مرورگر می شود:

پاسخ برگشتی از fetch
پاسخ برگشتی از fetch

همانطور که می بینید پاسخ ما یک شیء دارای خصوصیات و متدهای خاصی است، به طور مثال یک body و یک header و status و... را دارد. شما می توانید از قسمت کنسول مرورگر تمام این شیء را بررسی کنید. مثلا یکی از متدهای آن text است و ما می توانیم آن را به شکل زیر امتحان کنیم:

// Get local text file data
function getText() {
    fetch('test.txt')
        .then(function (res) {
            console.log(res.text());
        });
}

حالا در کنسول مرورگر یک promise را دریافت می کنیم:

برگشت دادن یک promise از متد text
برگشت دادن یک promise از متد text

همانطور که از جلسه ی قبل یاد گرفتیم برای دریافت پاسخ از promise ها باید از then استفاده کنیم. بنابراین می توانیم res را از then بالا return کرده و یک then دیگر به این زنجیره متصل کنیم:

// Get local text file data
function getText() {
    fetch('test.txt')
        .then(function (res) {
            return res.text();
        })
        .then();
}

به زبان ساده تر هر جا promise داشتید می توانید با استفاده از then آن را دریافت کنید. حالا مثل دفعه ی قبل یک تابع ساده را به این then پاس می دهیم که مقدار را به صورت یک پارامتر دریافت می کند (من نامش را data می گذارم) و آن را نیز console.log می کنیم:

// Get local text file data
function getText() {
    fetch('test.txt')
        .then(function (res) {
            return res.text();
        })
        .then(function (data) {
            console.log(data);
        })
}

با اجرای کد بالا مقدار this is a sample text file را که درون فایل خودمان نوشته بودیم دریافت می کنیم. البته همیشه از متد res.text استفاده نمی کنیم بلکه اگر سر و کارمان با json باشد باید از res.json استفاده کنیم (به موقعش آن را نیز بررسی می کنیم).

حالا که مطمئن شدیم این مقدار همان مقدار مورد نظر ما است می توانیم آن را درون صفحه ی HTML اضافه کنیم:

// Get local text file data
function getText() {
    fetch('test.txt')
        .then(function (res) {
            return res.text();
        })
        .then(function (data) {
            console.log(data);
            document.getElementById('output').innerHTML = data;
        })
}

با اضافه کردن کد بالا و رفرش کردن صفحه ی HTML شاهد حضور متن فایل test.txt درون صفحه ی HTML می شوید. البته بهتر است همیشه مراقب خطاهای ایجاد شده باشیم. بنابراین از دستور catch (برای اطلاعات بیشتر به جلسه ی قبل مراجعه کنید) استفاده می کنیم:

// Get local text file data
function getText() {
    fetch('test.txt')
        .then(function (res) {
            return res.text();
        })
        .then(function (data) {
            console.log(data);
            document.getElementById('output').innerHTML = data;
        })
        .catch(function (err) {
            console.log(err);
        });
}

ما هیچ خطایی نداریم تا این تابع اجرا شود بنابراین من به صورت دستی نام فایل را به test1.txt تغییر می دهم:

// Get local text file data
function getText() {
    fetch('test1.txt')
        .then(function (res) {
            return res.text();
        })

        // بقیه ی کدها

حالا در کنسول مرورگر خطا را مشاهده می کنیم:

خطای برگشتی از متد catch
خطای برگشتی از متد catch

خطای اول توسط ما کنترل نمی شود بلکه خود مرورگر آن را ساخته و نمایش خواهد داد اما خطای دوم که یک متن ساده است همان خطای catch می باشد.

اکنون می خواهیم فایل posts.json را نیز تست کنیم. من یک متن ساده برایتان آماده کرده ام که درون این فایل قرار دهید:

[
  {
    "title": "Post One",
    "body": "This is post one"
  },
  {
    "title": "Post Two",
    "body": "This is post two"
  },
  {
    "title": "Post Three",
    "body": "This is post three"
  }
]

حالا به فایل app.js برگردید تا یک event-listener برای دکمه ی دوم نیز تعیین کنیم:

document.getElementById('button2').addEventListener('click', getJson);

برای دریافت JSON نیز به همان شکل بالا عمل می کنیم البته تفاوت های ریزی نیز وجود دارد:

// Get local json data
function getJson() {
  fetch('posts.json')
    .then(function(res){
      return res.json();
    })
    .then(function(data) {
      console.log(data);
      let output = '';
      data.forEach(function(post) {
        output += `<li>${post.title}</li>`;
      });
      document.getElementById('output').innerHTML = output;
    })
    .catch(function(err){
      console.log(err);
    });
}

تنها تفاوت کد بالا با کد قبلی خود در این است که به جای res.text از res.json استفاده کرده ایم، نام فایل را تغییر داده ایم و سپس از آنجایی که با چندین شیء json سر و کار داشته ایم از یک حلقه ی forEach کمک گرفته ایم و تک تک title های این شیء را در div مورد نظرمان نمایش داده ایم.

برای دکمه ی سوم نیز می خواهیم از API خارجی استفاده کنیم بنابراین با یک event-listener شروع کرده و سپس تابع آن را تعریف می کنیم:

document.getElementById('button3').addEventListener('click', getExternal);

تابع این حالت هم دقیقا مثل توابع بالا است با این تفاوت که به جای نام فایل از یک url یا end-point استفاده می کنیم:

// Get from external API
function getExternal() {
  fetch('https://api.github.com/users')
    .then(function(res){
      return res.json();
    })
    .then(function(data) {
      console.log(data);
      let output = '';
      data.forEach(function(user) {
        output += `<li>${user.login}</li>`;
      });
      document.getElementById('output').innerHTML = output;
    })
    .catch(function(err){
      console.log(err);
    });
}

آدرسی که در بالا به تابع fetch داده ام یکی از endpoint های وب سایت گیت هاب است با ارسال درخواست به آن، حدود 100 (یا کمتر) کاربر آخر این وب سایت برایتان ارسال می شود. مقدار user.login نیز همان نام کاربری این افراد در گیت هاب است.

شما می توانید به سادگی کد خودتان را تست کنید و نباید هیچ مشکلی در فایل ها وجود داشته باشد.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری جاوا اسکریپت نامتقارن توصیه می‌کند:
نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.