Axios و Instane ها (پایان فصل 6)

22 بهمن 1399
Axios و Instane ها (پایان فصل 6)

پیش فرض های سراسری

برخی اوقات شما نمی خواهید برای اعمال تنظیمات سراسری درخواست ها را intercept کنید (متوقف کنید) بنابراین نیازی به استفاده از interceptor ها نیست و کافی است تنظیمات خود را به صورت سراسری به Axios بدهید. مثلا فرض کنید url ارسال درخواست ها در برنامه ی شما همیشه یک url ثابت است. مثلا url همیشه با https://jsonplaceholder.typicode.com شروع شده و در ادامه چیزی مثل posts/ دارد. از آنجایی که این قسمت همیشه ثابت است، بهتر است که https://jsonplaceholder.typicode.com را برداریم و درخواست هایمان را بدین شکل ارسال کنیم:

axios.get('/posts')

برای انجام این کار به فایل Index.js می رویم. این فایل محل مناسبی برای انجام این کار است چرا که قبل از بقیه ی اجزاء برنامه بارگذاری می شود. سپس می گوییم:

axios.defaults

defaults یک شیء است که مقادیر ثابت و پیش فرض را درون خود نگه میدارد. سپس می گوییم:

axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';

با این کار قسمت ثابت url را به عنوان baseURL تعریف کرده ایم تا تمام درخواست ها به آن متصل شده و سپس ارسال شوند. حالا به ترتیب به فایل های مختلف می رویم و درخواست هایمان را ویرایش می کنیم؛ ابتدا فایل Blog.js:

componentDidMount() {
    axios.get('/posts')
    .then(response => {

    // بقیه ی کد ها

سپس فایل NewPost.js:

    postDataHandler = () => {
        const post = {
            title: this.state.title,
            body: this.state.content,
            author: this.state.author
        }
        axios.post('/posts', post).then(response => {
            console.log(response);
        })
    }

سپس در فایل FullPost.js یک درخواست برای دریافت پست و یک درخواست برای حذف (delete) پست داریم. به ترتیب دریافت پست:

    componentDidUpdate() {
        if (this.props.id) {
            if (!this.state.loadedPost || (this.state.loadedPost && this.state.loadedPost.id !== this.props.id)) {
                axios.get('posts/' + this.props.id).then(Response => {
                    // console.log(Response);
                    this.setState({ loadedPost: Response.data });
                });
            }

        }
    }

و حذف پست:

    deletePostHandler = () => {
        axios.delete('posts/' + this.props.id).then(response => {
            console.log(response);
        });
    }

حالا اگر به مرورگر بروید، همه چیز سالم است و مانند قبل کار می کند منتها دیگر نیازی نیست برای هر درخواست url کامل را بنویسیم و حجم کد را بالا ببریم.

البته baseURL تنها چیزی نیست که برای ما قابل تعریف است. ما می توانیم چنین کاری انجام دهیم:

axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';
axios.defaults.headers.common['Authorization'] = 'AUTH TOKEN';

header های common (به معنی «رایج» یا «مشترک») یعنی header هایی که برای انواع مختلف درخواست ها استفاده می شوند. ما در ایجا از یک header به نام 'Authorization' (احراز هویت) استفاده کرده ایم تا اگر درخواست های شما دارای AUTH TOKEN (توکن احراز هویت) بود آن را از اینجا تنظیم کنید. توکن های احراز هویت روش جدیدتری برای شناسایی کاربران است که از روش های قدیمی (مانند استفاده از کوکی ها) بهتر عمل می کند. شما می توانید با یک سرچ ساده در این مورد اطلاعات مورد نظر را کسب کنید.

همچنین می توان گفت:

axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';
axios.defaults.headers.common['Authorization'] = 'AUTH TOKEN';
axios.defaults.headers.post['Content-Type'] = 'application/json';

در اینجا یک header برای درخواست های post ایجاد کرده ایم که فقط این نوع از درخواست ها را تحت تاثیر قرار می دهد. در کد بالا 'Content-Type درخواست های POST را روی application/json تنظیم کرده ایم (این همان حالت پیش فرض است و نیازی نیست این کار را انجام دهید). حالا اگر به مرورگر بروید، در قسمت headers از شیء برگردانده شده می توانید AUTH TOKEN را مشاهده کنید:

تنظیم header ها به صورت سراسری در Axios
تنظیم header ها به صورت سراسری در Axios

همچنین اگر از قسمت Add a Post در برنامه یک درخواست POST ایجاد کنیم و سپس به کنسول مرورگر نگاهی بیندازیم، علاوه بر AUTH TOKEN هدر دوم (content-type) نیز قابل مشاهده خواهد بود:

درخواست های POST و توکن احراز هویت
درخواست های POST و توکن احراز هویت

به همین سادگی!

Instance ها

این قابلیت (تنظیمات پیش فرض سراسری) بسیار کاربردی و جالب است اما برخی اوقات می خواهیم baseURL برای برخی از قسمت های برنامه یک چیز و برای برخی از قسمت های دیگر چیز دیگری باشد. Axios برای حل این مشکل Instance ها (به معنی «نمونه») را معرفی کرده است. برای آشنایی با این قابلیت یک فایل به نام Axios.js در کنار فایل Index.js بسازید (یعنی درون پوشه ی src) و درون آن Axios را import کنید:

import axios from 'axios';

سپس باید با استفاده از یک متد به نام create (این متد متعلق به axios است):

const instance = axios.create();

این متد یک instance (نمونه یا کپی) از شیء axios می سازد. حالا باید به عنوان پارامتر یک شیء جاوا اسکریپتی به آن بدهیم که حاوی پیش فرض های مورد نظر ما باشد. به طور مثال:

const instance = axios.create({
    baseURL: 'https://jsonplaceholder.typicode.com'
});

یعنی baseURL خود را بدین شکل تنظیم کرده ایم. در واقع در اینجا یک نمونه از axios را داریم ولی می توانیم بی نهایت مورد نمونه از شیء axios ایجاد کنیم و از هر کدام در جای خاصی از برنامه مان استفاده کنیم. یادتان باشد که کد زیر را از فایل index.js حذف یا کامنت کنید تا دو بار baseURL را تعریف نکرده باشیم:

axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';

instance ما همان تنظیمات پیش فرض را خواهد داشت که در index.js نوشته بودیم اما اگر چیزی در index.js باشد و در عین حال ما هم آن را در instance خود تعریف کرده باشیم، مورد instance اولویت بالاتری داشته و موارد دیگر را override می کند. به طور مثال به کد زیر در index.js توجه کنید:

axios.defaults.headers.common['Authorization'] = 'AUTH TOKEN';

ما می توانیم این کد را باقی بگذاریم و برخلاف baseURL آن را کامنت نکنیم اما آن را کپی کرده و در فایل axios.js قرار می دهیم:

import axios from 'axios';

const instance = axios.create({
    baseURL: 'https://jsonplaceholder.typicode.com'
});

instance.defaults.headers.common['Authorization'] = 'AUTH TOKEN FROM INSTANCE';

export default instance;

اگر دقت کنید به جای axios.defaults مقدار instance.defaults را قرار داده ایم؛ بدین صورت تمام درخواست هایی که از طریق این instance ساخته شوند، این مقدار پیش فرض را برای هدرهای خودشان خواهند داشت. متن AUTH TOKEN را نیز تغییر داده ام تا بعدا بدانیم هر مقدار به کدام instance تعلق دارد. در آخر نیز آن را export کرده ایم تا در جای دیگر از آن استفاده کنیم.

حالا برای استفاده از این instance به فایل Blog.js می رویم. در ابتدای این فایل axios را import کرده ایم تا درخواست دریافت پست ها و... را با آن انجام دهیم اما شما آن را مانند من کامنت کنید:

// import axios from 'axios';

حالا به جای اینکه axios را وارد کنیم، instance خودمان را وارد می کنیم:

import axios from '../../axios';

البته شما می توانید هر نام دیگری برای axios انتخاب کنید (مثلا axiosInstance و...). اگر تمام فایل ها را ذخیره کرده و به مرورگر بروید مشاهده می کنید که همه چیز به خوبی کار می کند و مشکلی نداریم اما در قسمت کنسول مرورگر دیگر شاهد interceptor ها نیستیم. آیا می دانید چرا؟ به دلیل اینکه interceptor ها را برای شیء سراسری axios تعریف کرده بودیم:

axios.interceptors.request.use(request => {
    console.log(request);
    return request;
}, error => {
    console.log(error);
    return Promise.reject(error);
});

axios.interceptors.response.use(response => {
    console.log(response);
    return response;
}, error => {
    console.log(error);
    return Promise.reject(error);
});

تعریف هر دو interceptor با عبارت axios.interceptors شروع شده است که یعنی interceptor های ما مخصوص شیء سراسری Axios اند نه نمونه ای که ما از آن ساخته ایم.

همچنین اگر از قسمت Add Post در برنامه سعی کنید درخواستی ارسال کنید با خطا مواجه می شوید. چرا؟ به دلیل اینکه baseURL را از فایل index.js کامنت کردیم اما instance خود را فقط درون Blog.js وارد (import) کرده ایم. بنابراین به خاطر import نشدن instance درون فایل index.js و فایل های دیگر، url تمام درخواست ها خراب و غلط می باشد. برای حل این مشکل می توانیم به فایل index.js رفته و baseURL را از حالت کامنت در بیاوریم:

axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';
axios.defaults.headers.common['Authorization'] = 'AUTH TOKEN';
axios.defaults.headers.post['Content-Type'] = 'application/json';

در این حالت از پکیج axios به صورت پیش فرض در همه جا استفاده می کنیم (baseURL در تمام قسمت های برنامه همان مورد بالا است اما در جایی که از instance استفاده کنیم مقدار های پیش فرض جدید اعمال خواهند شد؛ مثلا اگر baseURL در instance متفاوت باشد و در قسمتی از برنامه از instance استفاده کنیم، حالت پیش فرض سراسری override می شود.

حالا می توانیم به فایل axios.js برویم و interceptor هایی را برای این instance خود بسازیم. مثلا:

import axios from 'axios';

const instance = axios.create({
    baseURL: 'https://jsonplaceholder.typicode.com'
});

instance.defaults.headers.common['Authorization'] = 'AUTH TOKEN FROM INSTANCE';

//instance.interceptors.request...

export default instance;

چون در جلسه ی قبل مفصلا در مورد interceptor ها و تعریف آن ها صحبت کردیم، اینجا به صورت کامنت قالب کلی استفاده از interceptor را مشخص کرده ام و توضیح اضافه نمی دهم. ما در این فصل یاد گرفتیم که چطور درخواست های HTTP را در برنامه های react ایجاد و ارسال کنیم. همچنین کار با کتابخانه ی بسیار عالی axios را یاد گرفتیم. امیدوارم از این فصل لذت برده باشید.

دانلود کدهای کامل این فصل

در فصل بعدی به پروژه ی همبرگر ساز برمی گردیم تا قابلیت ایجاد درخواست های HTTP را به آن اضافه کنیم که تمرین خوبی برای این فصل محسوب می شود.

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

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