Mongez Http, пакет на базе Axios для управления http-запросами лучше, чем вы делаете это в своих проектах


Введение

Как указано в заголовке, [пакет Mongez http](https://github.com/hassanzohdy/mongez-http) — это библиотека на базе Axios для управления ajax-запросами (и node js тоже), но на профессиональном уровне.

Этот пакет построен на Axios, поэтому если вы хорошо знакомы с Axios, вы будете знакомы с остальной частью статьи.

Установка

Использование npm

npm i @mongez/http

Используя Yarn

yarn add @mongez/http

После установки создайте файл http-config.ts в вашем проекте (или .js, рекомендуется использовать typescript), чтобы мы могли задать наши конфигурации.

Импортируйте этот файл на ранней стадии вашего проекта, в начале src/index.ts, например, или в записи главного файла проекта.

Давайте определим наш файл конфигурации.

// http-config.ts
import { setHttpConfigurations } from '@mongez/http';

setHttpConfigurations({
    baseUrl: 'https://jsonplaceholder.typicode.com',    
});
Войти в полноэкранный режим Выйти из полноэкранного режима

Для демонстрации мы будем использовать JSON Placeholder API, чтобы вы могли увидеть реальные результаты.

На данный момент все в порядке, теперь давайте попробуем сделать несколько красивых запросов.

Вы можете следить за тем, что происходит в песочнице.

Обработчик конечных точек

После того, как мы установили наши конфигурации, теперь мы можем использовать наш обработчик endpoint, который может быть использован в любом месте вашего приложения.

Что такое обработчик конечных точек? По сути, это экземпляр Axios, но с некоторыми изменениями.

Чтобы сделать наш проект чистым и более структурированным, давайте создадим каталог services в вашем проекте src, внутри которого мы добавим файл todo-service.ts.

// todo-service.ts
import endpoint from "@mongez/http";

export function getTodoList() {
  return endpoint.get("/todo");
}
Вход в полноэкранный режим Выход из полноэкранного режима

Итак, мы импортировали обработчик конечной точки и экспортировали функцию для получения списка Todo.

Как вы можете видеть, мы просто добавили в метод get только относительный путь к базовому api url /todo, так что вам не придется указывать свой базовый url в каждом запросе.

Использование

Теперь мы настроили наши конфигурации, обработали наши сервисы, давайте использовать его.

В вашем App.ts или если вы используете react в хуке useEffect вызовите службу конечной точки.

// App.ts
import { getTodoList } from 'src/services/todo-service';

// let's make an ajax call

getTodoList().then((response) => {
  console.log(response.data);
});
Вход в полноэкранный режим Выход из полноэкранного режима

Размещение данных

Мы рассмотрели, как работать с GET-запросами, теперь давайте посмотрим, как работать с POST-запросами.

Для демонстрации я использую React, чтобы сделать простую страницу создания аккаунта.

// RegisterPage.tsx
export default function RegisterPage() {
  return (
    <>
      <form>
        <input name="name" type="text" placeholder="Your Name" />
        <br />
        <input name="email" type="email" placeholder="Email Address" />
        <br />
        <input name="password" type="password" placeholder="Password" />
        <br />
        <button>Create Account</button>
      </form>
    </>
  );
}
Вход в полноэкранный режим Выход из полноэкранного режима

Мы только что сделали простой базовый ui для предварительного просмотра формы создания аккаунта, теперь, чтобы отправить форму, нам нужно получить данные, которые будут отправлены, но перед этим давайте создадим файл auth-service.ts в нашей директории services.

// src/services/auth-service.ts
import endpoint from "@mongez/http";

export function register(data: any) {
    return endpoint.post('/users', data);
}
Вход в полноэкранный режим Выход из полноэкранного режима

Мы создали обработчик регистра, теперь давайте снова вернемся к нашему ui.

// RegisterPage.tsx
import { useState } from "react";
import { register } from "./services/auth-service";

export default function RegisterPage() {
  const [data, setData] = useState({
    email: "",
    name: "",
    password: ""
  });

  const createAccount = (e: any) => {
    e.preventDefault();

    register(data).then((response) => {
      console.log(response.data);
    });
  };

  return (
    <>
      <form onSubmit={createAccount}>
        <input
          name="name"
          onChange={(e) => {
            setData({
              ...data,
              name: e.target.value
            });
          }}
          type="text"
          placeholder="Your Name"
        />
        <br />
        <input
          onChange={(e) => {
            setData({
              ...data,
              email: e.target.value
            });
          }}
          name="email"
          type="email"
          placeholder="Email Address"
        />
        <br />
        <input
          onChange={(e) => {
            setData({
              ...data,
              password: e.target.value
            });
          }}
          name="password"
          type="password"
          placeholder="Password"
        />
        <br />
        <button>Create Account</button>
      </form>
    </>
  );
}
Вход в полноэкранный режим Выход из полноэкранного режима

Мы создали простое состояние для хранения данных нашей формы внутри него, чтобы мы могли отправить объект на сервер, после отправки вы увидите консольный лог с теми же данными, которые мы заполнили, так как api сервер возвращает те же данные с id, обычно 11.

Данные формы и загрузка

Это было хорошо, но что если мы хотим загрузить файлы или изображения? В этом случае нам придется использовать FormData, однако это не обязательно, так как пакет обрабатывает это за вас, давайте немного расширим наш код.

Обратите внимание, что это не будет работать, так как JSON Placeholder принимает только json, но не form-data запросы.

// RegisterPage.tsx
import { register } from "./services/auth-service";

export default function RegisterPage() {
  const createAccount = (e: any) => {
    e.preventDefault();

    // as you can see we skipped the state to store the data as we'll fetch it from the form inputs directly
    const formData = new FormData(e.target);

    register(formData).then((response) => {
      console.log(response.data);
    });
  };

  return (
    <>
      <form onSubmit={createAccount}>
        <input
          name="name"
          type="text"
          placeholder="Your Name"
        />
        <br />
        <input
          name="email"
          type="email"
          placeholder="Email Address"
        />
        <br />
        <input
          name="password"
          type="password"
          placeholder="Password"
        />
        <br />
        <button>Create Account</button>
      </form>
    </>
  );
}
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь мы отправили запрос данных формы, как упоминалось ранее, это можно сделать проще, просто передав элемент формы The e.target element непосредственно в конечную точку.

// RegisterPage.tsx
import { register } from "./services/auth-service";

export default function RegisterPage() {
  const createAccount = (e: any) => {
    e.preventDefault();

    register(e.target).then((response) => {
      console.log(response.data);
    });
  };

  return (
    <>
      <form onSubmit={createAccount}>
        <input
          name="name"
          type="text"
          placeholder="Your Name"
        />
        <br />
        <input
          name="email"
          type="email"
          placeholder="Email Address"
        />
        <br />
        <input
          name="password"
          type="password"
          placeholder="Password"
        />
        <br />
        <button>Create Account</button>
      </form>
    </>
  );
}
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь мы обработали отправку данных в serer, используя три метода:

  1. Передача объектов Plain.
  2. Передача объектов FormDta.
  3. Передача объектов FormElement.

Конечная точка Restful

Еще одной мощной особенностью Mongez Http является класс Restful, который управляет несколькими запросами в рамках одного класса.

Давайте снова вернемся к нашему todo-service.ts и добавим класс Restful endpoint для управления им.

// todo-service.ts
import endpoint, { RestfulEndpoint } from "@mongez/http";

class TodoService extends RestfulEndpoint {
  /**
   * {@inheritDoc}
   */
  public route = "/todos";
}

const todoService: TodoService = new TodoService();

export default todoService;

// will be kept only for the demo
export function getTodoList() {
  return endpoint.get("/todos");
}
Вход в полноэкранный режим Выход из полноэкранного режима

Итак, что это было? Ну, в основном класс RestfulEndpoint управляет основными запросами restful api в 6 основных методах.

Давайте посмотрим, как использовать его в нашем реальном коде.

// TodoList.tsx
import { useEffect, useState } from "react";
import todoService from 'src/services/todo-service';

export default function TodoList() {
  const [items, setItems] = useState([]);
  const [isLoading, setLoading] = useState(true);

  useEffect(() => {
    todoService.list().then((response) => {
      setItems(response.data);
      console.log(response.data);
      setLoading(false);
    });    
  }, []);

  if (isLoading) return <h1>Loading....</h1>;

  return (
    <>
      {items.map((item) => (
        <div key={item.id}>{item.title}</div>
      ))}
    </>
  );
}
Вход в полноэкранный режим Выход из полноэкранного режима

Мы только что вызвали метод list, чтобы сделать запрос,

Мы также можем определить параметры запроса к запросу списка, передав ему объект, например

todoService.list({
    limit: 15,
    active: 1,
}); // will make GET /todos?limit=15&active=1
Войти в полноэкранный режим Выйти из полноэкранного режима

Чтобы получить одну запись, метод service.get() сделает это за вас.

const todoId = 1;

todoService.get(todoId).then(response => {
    console.log(response.data);
});
Войти в полноэкранный режим Выйти из полноэкранного режима

Прерывание запросов

Еще одна хорошая возможность — это перехват запроса в переменную, чтобы вы могли отменить/заменить его в любое время, например, при отправке запроса в useEffect, для этого можно использовать функцию lastRequest.

// TodoList.tsx
import { lastRequest } from "@mongez/http";
import { useEffect, useState } from "react";
import todoService from 'src/services/todo-service';

export default function TodoList() {
  const [items, setItems] = useState([]);
  const [isLoading, setLoading] = useState(true);

  useEffect(() => {
    todoService.list().then((response) => {
      setItems(response.data);
      console.log(response.data);
      setLoading(false);
    });
      .catch((error) => {
        console.log(error);
      });

    // catch the request
    let request = lastRequest();

    return () => {
      request.abort();
    };
  }, []);

  if (isLoading) return <h1>Loading....</h1>;

  return (
    <>
      {items.map((item) => (
        <div key={item.id}>{item.title}</div>
      ))}
    </>
  );
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Put To Post

В некоторых языках, таких как PHP, вы не можете напрямую загружать файлы или изображения, используя метод запроса PUT, но некоторые фреймворки, такие как Laravel, сделали обходной путь для решения этой проблемы, делая запрос POST с ключом _method в паре с PUT в качестве его значения, чтобы вы могли прослушать запрос как запрос PUT, Это также можно сделать, установив ключ putToPost в конфигурации http в true, но ваш код останется тем же.

Перед использованием запрос будет выглядеть примерно так

// some-service.ts
import endpoint from '@mongez/http';

export function updateProfile(data: any) {
    return endpoint.put('/me', data); 
}

updateProfile({
    username: 'hasan',
    password: '123'
}); 

// PUT /me request and { username: hasan, password: 123 } as data
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь активируем флаг.

// http-config.ts

import { setHttpConfigurations } from '@mongez/http';

setHttpConfigurations({
    baseUrl: 'https://jsonplaceholder.typicode.com',    
    putToPost: true,
});
Войти в полноэкранный режим Выйти из полноэкранного режима

После активации

// some-service.ts
import endpoint from '@mongez/http';

export function updateProfile(data: any) {
    return endpoint.put('/me', data); 
}

updateProfile({
    username: 'hasan',
    password: '123'
}); 

// PUT /me request and { username: hasan, password: 123, _method: PUT } as data
Войти в полноэкранный режим Выйти из полноэкранного режима

Таким образом, вы ничего не измените в своем коде, и если ваш api когда-нибудь пренебрежет этой функцией и разрешит прямую загрузку, вы просто отключите флаг, и все будет в порядке.

События HTTP / перехватчики

Последняя функция, о которой я хотел бы рассказать, это события запроса или перехватчики, это чрезвычайно полезный способ манипулировать запросами до их отправки или даже ответом, когда они уже отправлены.

Это можно сделать с помощью обработчика endpointEvents, он предоставляет 4 хороших перехватчика для работы.

Перехватчик beforeSending получает конфигурацию запроса axios для своего обратного вызова, мы можем, например, установить заголовок Authorization.

import { AxiosRequestConfig } from "axios";
import { AxiosRequestConfig } from "axios";
import { endpointEvents } from '@mongez/http';

// This is triggered before sending any request
endpointEvents.beforeSending((config: AxiosRequestConfig): EventSubscription => {
    config.headers.Authorization = 'key xxx';
});
Вход в полноэкранный режим Выход из полноэкранного режима

Заключение

Основная цель пакета — сделать ваш код организованным, хорошо структурированным и простым в поддержке или масштабировании. Как уже упоминалось ранее, он основан на Axios, поэтому любая функция, которая может понадобиться в Axios, может быть использована и здесь.

Для получения более подробной документации по пакету, не стесняйтесь посетить репозиторий Github.

Надеюсь, вам понравится пакет, и любые отзывы будут приняты с благодарностью.

Наслаждайтесь и удачного кодинга.

Оцените статью
devanswers.ru
Добавить комментарий