HTTP и взаимодействие с сервером

HttpClient и отправка запросов

Последнее обновление: 15.11.2023

Для взаимодействия с сервером и отправки запросов по протоколу http применяется класс HttpClient. Этот класс определяет ряд методов для отправки различного рода запросов: GET, POST, PUT, DELETE. Данный класс построен поверх стандартного объекта в JavaScript - XMLHttpRequest.

Для использования этого класса в проект необходимо установить пакет "@angular/common":

{
    "name": "helloapp",
    "version": "1.0.0",
    "description": "First Angular 17 Project",
    "author": "Eugene Popov metanit.com",
    "scripts": {
        "ng": "ng",
		"start": "ng serve",
		"build": "ng build"
    },
    "dependencies": {
        "@angular/common": "~17.0.0",
        // остальные пакеты
    },
    "devDependencies": {
         
        // остальные пакеты
    }
}

И также в компоненте должен быть импортирован класс HttpClientModule из пакета "@angular/common/http":

import { Component} from "@angular/core";
import { HttpClientModule} from "@angular/common/http";

@Component({
    imports: [HttpClientModule],

Вначале рассмотрим выполнение простейших GET-запросов. Пусть у нас есть стандартная структура проекта:

HttpClientModule в Angular

Определим обращение по сети к файлу json, который будет хранить некоторые данные. Папка собственно файлов приложения - это папка src. Поэтому в ней определим новую папку assets. И далее добавим в папку src/assets файл data.json, который будет представлять данные:

{
	"name": "Bob",
	"age": 28
}

Для представления данных в папку src/app добавим новый файл user.ts и определим в нем следующий код:

export class User{
    constructor(public name:string, public age:number){}
}

Файл проекта после изменений:

Json as an asset in Angular 17

Для оправки запроса определим в компоненте AppComponent следующий код:

import { Component, OnInit} from "@angular/core";
import { HttpClient, HttpClientModule} from "@angular/common/http";
import {User} from "./user";

@Component({
    selector: "my-app",
    standalone: true,
    imports: [HttpClientModule],
    template: `<div>
                    <p>Имя пользователя: {{user?.name}}</p>
                    <p>Возраст пользователя: {{user?.age}}</p>
               </div>`
})
export class AppComponent implements OnInit { 
   
    user: User | undefined;
 
    constructor(private http: HttpClient){}
      
    ngOnInit(){
          
        this.http.get("assets/data.json").subscribe({next:(data:any) => this.user=new User(data.name, data.age)});
    }
}

В данном случае в шаблоне выводятся данные объекта User, которые мы хотим получить с сервера. Однако загрузка данных, скажем, в конструкторе компонента не очень желательна. В этом плане метод ngOnInit(), который определен в интерфейсе OnInit и который вызывается при инициализации компонента представляет более предпочтительное место для загрузки данных. В конструкторе же мы просто получаем сервис HttpClient.

Далее в методе ngOnInit() получаем данные из сервиса. Сам метод http.get() возвращает объект Observable<Object>. Observable представляет своего рода поток, и для прослушивания событий из этого потока применяется метод subscribe. Этот метод определяет действие над результатом запроса - полученными с сервера данными. В данном случае действие определено с помощью параметра next в виде стрелочной функции. Причем поскольку между схемой класса User и данными из файла json есть прямое сопоставление, то получаемые данные мы можем передать в конструктор класса User:

(data:any) => this.user=new User(data.name, data.age)

Поскольку файл json представляет вспомогательный файл, то нам надо указать это angular cli в файле angular.json с помощью параметра "assets": ["src/assets"]:

{
  "version": 1,
  "projects": {
    "helloapp": {
      "projectType": "application",
      "root": "",
      "sourceRoot": "src",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/helloapp",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": ["zone.js"],
            "tsConfig": "tsconfig.json",

            "assets": ["src/assets"],

            "aot": true
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "buildTarget": "helloapp:build"
          }
        }
      }
    }
  }
}

В итоге при запуске веб-страницы мы увидим загруженные данные из файла data.json.

HttpService в Angular 17

Создание сервиса

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

Поэтому для работы с http добавим в папку src/app новый файл http.service.ts со следующим содержимым:

import {Injectable} from "@angular/core";
import {HttpClient} from "@angular/common/http";
 
@Injectable()
export class HttpService{
 
    constructor(private http: HttpClient){ }
     
    getData(){
        return this.http.get("assets/data.json")
    }
}

Для отправки запросов сервис получает объект HttpClient. К классу применяется декоратор @Injectable, который гарантирует, что встроенный механизм внедрения зависимостей сможет создать объект этого класса и передать его в качестве зависимости в другой объект (в другой сервис или компонент).

Для выполнения get-запроса у объекта HttpClient вызывается метод get(), в который передается адрес запроса - в нашем случае json-файл с данными.

Теперь используем этот сервис в компоненте AppComponent:

import { Component, OnInit} from "@angular/core";
import { HttpClientModule} from "@angular/common/http";

import { HttpService} from "./http.service";
import {User} from "./user";

@Component({
    selector: "my-app",
    standalone: true,
    imports: [HttpClientModule],
    template: `<div>
                    <p>Имя пользователя: {{user?.name}}</p>
                    <p>Возраст пользователя: {{user?.age}}</p>
               </div>`,
    providers: [HttpService]
})
export class AppComponent implements OnInit { 
   
    user: User;
      
    constructor(private httpService: HttpService){}
      
    ngOnInit(){
          
        this.httpService.getData().subscribe({next:(data:any) => this.user=new User(data.name, data.age)});
    }
}

Загрузка сложных данных

В примерах выше определение json-файла соответствует определению класса User, поэтому простое присвоение this.user=new User(data.name, data.age) пройдет успешно. И подобным образом мы можем загружать и другие более сложные данные. Так, изменим файл data.json следующим образом:

{ 
    "userList":
    [{
        "name": "Bob",
        "age": 28
    },{
        "name": "Tom",
        "age": 45
    },{
        "name": "Alice",
        "age": 32
    }]
}

В классе HttpService также загружаем данные из "data.json":

import {Injectable} from "@angular/core";
import {HttpClient} from "@angular/common/http";
  
@Injectable()
export class HttpService{
  
    constructor(private http: HttpClient){ }
      
    getData(){
        return this.http.get("assets/data.json")
    }
}

И изменим код компонента:

import { Component, OnInit} from "@angular/core";
import { HttpClientModule} from "@angular/common/http";

import { HttpService} from "./http.service";
import {User} from "./user";

@Component({
    selector: "my-app",
    standalone: true,
    imports: [HttpClientModule],
    template: `<ul>
                @for(user of users; track $index){
                    <li>
                        <p>Имя пользователя: {{user?.name}}</p>
                        <p>Возраст пользователя: {{user?.age}}</p>
                    </li>
            }
            </ul>`,
    providers: [HttpService]
})
export class AppComponent implements OnInit { 
   
    users: User[]=[];
     
    constructor(private httpService: HttpService){}
      
    ngOnInit(){
          
        this.httpService.getData().subscribe({next: (data: any) => this.users=data["userList"]});
    }
}

В данном случае мы хотим получить массив объектов User. Но напрямую данные из файла "data.json" не соответствуют массиву. Массив в файле определен по ключу "userList". Поэтому, используя данный ключ, мы достаем нужные данные из ответа сервера: this.users=data["userList"].

Загрузка данных в Angular 17
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850