# api request-ების ორგანიზირება

## პრობლემა

თუ ჩვენი აპლიკაცია ზომაში პატარაა არანაირი პრობლემა არ იქნება რომ ჩვენ ყველა api request  ეგრევე inline ვწეროთ და ყველა ჯერზე როცა ეს რექუესტი დაგვჭირდება ახლიდნ ვადგინოთ ეს სტრინგი, მაგრამ ცოტა მოზრდილ აპლიკაციებში ეს უკვე პრობლემა გახდება.

ჩვენ გვექნება api route-ები რომელიც თითქმის ყველა გვერდზე შეიძლება დაგვჭირდეს და შეცდომის დაშვება ასეთ ქეისებში საკმაოდ ადვილი იქნება.

api გზის არასწორად გაწერის პრობლემას თუ დავივიწყებთ შემდეგი პრობლემა ის არის რომ შეიძლება აპლიკაციაში დაგვჭირდეს გაგზავნამდე რაღაც ინფორმაციის შემოწმება ან მიბმა ყველა რაუტზე, მაგალითად გვინდა რომ auth token მივაბათ ყველა რექუესტს ეს ჩვენ მაშინ ყველგან უნდა ვქნათ სადაც ვიყენებთ api-ს და გამორჩენის რისკი აქაც საკმაოდ დიდია

## სერვისები

ზემოთხსენებული პრობლემის მოგვარება არის შესაძლებელი სერვისებით. იდეა არის რომ ყველა api route-ისთვის დავწერთ ფუნქციას რომელიც ამ რაუტზე აგზავნის ინფორმაციას, ასეთ შემთხვევაში ჩვენ როცა მოგვინდება რომ მომხმარებლის ინფორმაცია წამოვიღოთ სულ ერთ ადგილს გავივლით და სულ დარწმუნებული ვიქნებით რომ სწორ api-ზე ვაგზავნით მოთხოვნას და შეცდომის რისკი საკმაოდ მცირდება.

მაგრამ ამ ქეისშიც შეიძლება მოგვიწიოს ხოლმე სრული api url-ის გაწერა რაც  ასევე შეიძლება შეგვეშალოს, ნუ რათქმაუნდა შეგვიძლია რომ  api ცალკე ცვალდში გავიტანოთ და სულ ეგ საწყისი წერტილი გამოვიყოთ მაგრამ ესეც შეიძლება დაგავივწყდეს, ბევრად აჯობებს თუ რაიმე ერთი ობიექტი გვექნება ინფორმაციის მოსათხოვნად.

ამისთვის ჩვენ შეგვიძლია გამოვიყენოთ axios instance-ები სადაც მარტო ერთ ადგილზე გავწერთ api-ს სრულ გზას, საჭირო ჰედერებს და სხვა ინფორმაციას და ყველა ჯერზე უბრალოდ ამ ინსტანციას გამოვიყენებთ იმის მაგივრად რომ ახლიდან ვწეროთ ყველაფერი.

## იმპლემტაციის დეტალები

აპლიაკციის რუტში უნდა შევქმნათ საქაღლდე services მაგის შიგნით უდნა შევქმნათ ფაილი axios.{ts,js} სადაც დავწერთ ამდაგვარ რაღაცას.

```javascript
import axios from 'axios';

const instance = axios.create({
  baseURL: https://my-amazing-backend.com/api/,
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
});

export default instance;

```

მერე კერძო api request-ისთვის ფუნქციის შექმნისთვის უნდა გავაკეთოთ ახალი ფაილი /services საქაღალდეში და დავარქვათ ნებისმიერი სახელი, უნდა ვეცადოთ რომ ლოგიკურად დავყოთ ეს ფაილები: ავტორიზაციის რექუესტები ცალკე, ბლოგების წამოყღება ცალკე და ასე შემდეგ.

ამ მაგალითისთვის შევქმნი საქაღალდეს submissions.ts და შიგნით ასეთ რაღაცას ჩავწერ

{% code overflow="wrap" lineNumbers="true" %}
```javascript
import { AxiosResponse } from 'axios';
import { Submission } from "types"

export const getSubmissionsRequest = async (token: string, page: number, problemId): Promise<AxiosResponse<Submission[]>> => {
  return await axios.get('/submissions', {
    headers: {
      Authorization: `Bearer ${token}`,
    },
    params: {
      page,
      problemId,
    },
  });
};
```
{% endcode %}

და შემდეგ ჩვენ როცა დაგვჭირდება submission-ების წამოღება შეგვიძლია რომ სულ ეს ფუნქცია გამოვიყენოთ, ამის ბონუსი ის არის რომ გზა არ შეგვეშლება, ts-ს საშუალებით დეკლარირებული იქნება თუ ზუსტად რა პარამეტრები ჭირდება ამ api-ს რომ იმუშაოს და შეცდომის შესაძლებლობა საკმაოდ კლებულობს.



### გამოყენების წესები / რჩევები

* სერვისი აუცილებლად უნდა იყოს camelCase-ში.
* სერვისიდან დააბრუნეთ ხოლმე მთლაინი რექუესტი, არ დააბრუნოთ მხოლოდ data, შესაძლებელია რომ სტატუსი დაგჭირდეთ ხოლმე მომავალში, ან მესიჯი
* თუ იყენებთ ts-ის ან jsdoc-ს აუცულებალად გააკეთეთ ტიპირება დაბრუნების ტიპის და პარამეტრების, any-ს გამოიყნება არ არის მიზანშეწონილი, რადგანაც ამ შემთხვევაში სერვისების ერთ-ერთი უდიდესი ბონუსი იკარგება
* როცა აქსიოსს ვიყენებთ ქუერი პარამეტრები არ გადავცეთ ეგრევე სტრინგიად რაუტში (მაგ `submissions/?page=1&problemId`) და გადაეცით მეორე პარამეტრად კონფიგურაციაში params ობიექტში, ამის მიზეზი ის არის რომ ჯერ ერთი მახინჯია ასე დაწერა და მეორეც ერთი იმის გამო რომ აქსიოსი თქვენ მიერ მიწოდებულ გზას url-ად დაპარსავს და მოაშორებს +, whitespace, და სხვა ნიშნებს რომელებიც რაუტში არ შეიძლება, ამის გამო არასწორი ინფორმაცია გაიგზავნება და დამაბნეველი ბაგი გექნებათ
* დაყავით სერვისები ცალ-ცალკე ფაილებში, ერთად არ გქონდეთ
* დაყოფის მერეც ერთ ობიექტში არ ჩადოთ სერვისები კომფორტისთვის და დაჯგუფებისთვის, ეს არ არის კარგი იდეა tree shaking-ის გამო, შეიძლება დიდი ფაილები არ იყოს მაგრამ მაინც არ ღირს ერთ ობიექტში ფაილის სერვისების ჩადება, ჯობია ლოგიკურად ფაილების მიხედვით დაიყოს
