Angular 4 – урок по стороннім API

474

Від автора: Angular 4 чи тепер вже просто Angular – це потужний фреймворк для розробки адаптивних веб-додатків. Angular – хороший фреймворк, проте його можна дуже довго вивчати. У новачків виникають труднощі, коли вони вперше зустрічаються з Angular API, і це нормально. Найчастіше це призводить до того, що розробники відмовляються від фреймворку, вибираючи що-те, із чим уже знайомі. Angular дійсно не простий в освоєнні, це всеосяжний фреймворк, здатний створювати масштабовані, розширювані і долгоподдерживаемые програми. Він створює модульні проекти, які дотримуються кращим практикам хорошого дизайну. Angular набагато складніше, але в рівній мірі і краще будь-якого іншого фреймворка. Витратьте час на вивчення Angular – це інвестиції окупаються, і оплати будуть рости експоненціально.

Одна з перших завдань, яке розробникам потрібно зрозуміти, як це отримувати дані з інтернету. У Angular для цього є конкретна процедура. Вам може здатися, що код буде дуже багато, але в кінцевому підсумку це буде більш якісний код, який потім буде легше тестувати, налагоджувати і підтримувати. Цей процес можна розбити на маленькі кроки для кращого засвоєння.

Крок 1 (необов’язковий). Де ви зберігаєте конфіденційні дані?

Крок 1 необов’язково, але дуже рекомендується до виконання. Захистити інформацію можна кількома способами. Простий, кращий метод – ввести інформацію в файл environment.ts, розташований в папці app/environments. Якщо ви працюєте з Angular CLI (краще працювати в ній), то Angular вже створив const-об’єкт під назвою environment. Просто додайте в цей об’єкт пару «name:value», де name посилається на секретне «value». Тут ми будемо зберігати url api, будь-які ключі та інші дані. Наприклад, можна додати url api, щоб потім ми могли на нього посилатися.

export const environment = {
production: false
api_url: ‘http://jsonplaceholder.typicode.com/posts/’
};

Не забудьте додати app/environments/environment.ts файл .gitignore, щоб не перевіряти його у вихідному коді!

Крок 2: (необов’язковий). Як ви моделюєте дані?

Крок 2 необов’язково, але дуже рекомендується до виконання. Програми працюють з даними. Дані можуть являти собою зображення, пости, твіти, та що завгодно. Перш ніж працювати з даними, чи то в режимі RESTful чи ні, необхідно створити модель. Модель – відмінний спосіб моделювання і визначення даних. Крім того, моделі надають схему для подальшого збереження своїх екземплярів в базі даних. Переважно створювати модель в Angular через інтерфейс Typescript. Інтерфейс описує те, як повинні виглядати дані. Наприклад, якщо визначити інтерфейс Post, він може бути приблизно таким.

export interface Post {
userId: number;
id: number;
title: string;
body: string
}

Щоб полегшити доступ до файлу, його можна помістити в папку app.

Крок 3. Створення компонентів

Для обробки даних необхідно створити компоненти. Кількість компонентів і їх зв’язку залежать від факторів, які визначаються для кожного додатка самостійно. Наприклад, ми створимо 2 компонента, батьківський і дочірній. У Angular CLI можна використовувати скорочення: g – згенерувати, c – компонент. Таким чином, команди перетворюються в ng g c post і ng g c post-list. Тепер у нас є 2 компонента для обробки даних. За допомогою Http-модуля Angular можна витягати placeholder-дані з наших компонентів, однак це порушує принцип єдиної відповідальності. Замість цього ми будемо слідувати кращим практикам Angular Style Guide для отримання даних через сервіс.

Крок 4. Створення сервісу для отримання даних

Повернемося знову до Angular CLI і створимо сервіс. Сервіс можна створити з допомогою символу s: ng g s post. Команда створить файл post.service.ts імпортує PostService в app.module.ts. Команда також видасть попередження про те, що сервіс успішно створений, але до нього не визначений ні один провайдер. Це попередження нагадує нам, що для роботи з нашим сервісом його потрібно додати в масив providers у файлі app.module.ts. Дякую за нагадування, Angular!

// app.module.ts

// для стислості інший вилучений код
providers: [PostService], // added PostService to providers array
bootstrap: [AppComponent]
})
export class AppModule { }

Перш ніж ми почнемо працювати над нашим сервісом, давайте створимо файл rxjs-operators.ts, щоб імпортувати оператори Reactive Extensions, які нам знадобляться. Почнемо файл з імпорту 3 операторів:

// rxjs-operators.ts
import ‘rxjs/add/operator/catch’;
import ‘rxjs/add/operator/map’;
import ‘rxjs/add/operator/toPromise’;

Тепер потрібно імпортувати всього один рядок в наш файл post.service.ts, щоб отримати доступ до всіх трьом операторам – досить витончено.

// post.service.ts
import { Http Response } from ‘@angular/http’;
import { Injectable } from ‘@angular/core’;
import {Post} from ‘./post’;
import { Вами } from ‘rxjs/Вами’;
import ‘./rxjs-operators’;
import { environment } from ‘./../environments/environment’;
@Injectable()
export class PostService {
}

Зверніть увагу, що над PostService прописаний декоратор @Injectable, також ми імпортували Http Response модулі з @angular/http. Ми імпортували наш файл оточення, який налаштували в першому кроці, трохи пізніше ми його використовуємо. Також ми імпортували з Вами rxjs/Вами. Angular модуль Http тепер використовує observables за замовчуванням, тобто коли ми використовуємо метод GET, ми отримуємо відповіді вами. Якщо ви не знаєте, що це таке, почитайте. Вони нативно представлені в Angular, а скоро і в ECMAScript. Вони забезпечують методи складання асинхронних потоків даних, на які можна підписатися, об’єднати, маніпулювати і т. д. Почитайте на Github.

Наш PostService буде збирати дані по вебу, а конструктор повинен створювати об’єкт Http-модуля.

constructor(private http: Http) { }

Ми створимо метод getData, який буде посилати GET-запит на сервер і обробляти відповідь.

getData(): Вами {
return this.http.get(this.url)
.map(this.extractData)
.catch(this.handleError);
}

Перший рядок визначає функцію getData() типу Post. Не забувайте, що ми раніше створили інтерфейс post і імпортували Post в верх файлу. Ми повертаємо this.http.get(‘url’). Сервіс повертає відповідь, з яким ми будемо працювати в нашому компоненті. Запис http – об’єкт Http get – один з методів Http. Далі ми використовуємо оператор .map і передаємо в функцію extractData. Передавати функцію в map необов’язково. Якщо цього не робити, функцію getData() буде коротше і простіше для тестування і читання. Ми могли взагалі просто передати вміст extractData() оператор map.

private extractData(res: Response) {
let body = res.json();
return body || [];
}

В об’єкті відповіді є json-метод, який конвертує повернуту рядок у відповідне об’єктне представлення, що зберігається в пам’яті. Функція extractData() повертає body, який є json-рядком або порожнім масивом. Наша функція getData() використовує оператор .catch() для обробки помилок, передаючи їх у функцію handleError():

private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} – ${error.statusText}` : ‘Server error’;
console.error(errMsg);
return Вами.throw(errMsg);
}

Ми отримали PostService, який витягає дані та володіє методами для обробки відповідей та помилок. Весь сервіс post повинен виглядати так:

// post.service.ts
import { Injectable } from ‘@angular/core’;
import {Post} from ‘./post’;
import { Http Response } from ‘@angular/http’;
import { Вами } from ‘rxjs/Вами’;
import ‘./rxjs-operators’;
import { environment } from ‘./../environments/environment’;
@Injectable()
export class PostService {
private url = environment.api_url; // STEP ONE
constructor(private http: Http) {}
getData(): Вами<Post[]> {
return this.http.get(url)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body || [];
}
private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} – ${error.statusText}` : ‘Server error’;
console.error(errMsg); // log to console instead
return Вами.throw(errMsg);
}
}

Крок 5. Використання PostService

Ми створили PostService для збору даних, тепер давайте задіємо його. Відкрийте файл post-list.component.ts і імпортуйте обов’язкові файли.

import { Component, OnInit } from ‘@angular/core’;
import { PostService } from ‘../post.service’;
import { Post } from ‘../Post’;

Ми імпортуємо хук життєвого циклу OnInit, наш Post інтерфейс і PostService. Хук onInit можна використовувати для запуску будь-якого коду ініціалізації для нашого компонента. Це дозволяє видалити код ініціалізації з конструктора. Конструктор повинен бути якомога менше, щоб знизити залежність і полегшити тестування.

export class PostListComponent implements OnInit {
private posts: Post[] = [];
private errorMessage: any = “;
constructor(private postService: PostService) {
}

Зверніть увагу, що ми також створили 2 властивості PostListComponent – властивість posts типу Post і errorMessage типу any. Далі ми вставляємо наш PostService в конструктор з допомогою створення об’єкта postService. Зараз наш PostService буде витягати дані, і цей сервіс ми вставили в наш компонент. Все інше для підписки на вами, щоб ми могли отримувати json і відображати його в поданні. Ми визначили метод getPosts():

getPosts() {
this.postService.getData()
.subscribe(
posts => this.posts = posts,
error => this.errorMessage = error);
}

Метод getPosts() з допомогою об’єкта postService викликає getData. Пам’ятайте, що getData визначено у файлі post.service.ts і отримує дані з сервера через http.get(‘URL’). Далі ми підписуємося на вами і визначаємо наші властивості posts і error.

Крок 6. Виклик PostService в момент ініціалізації компонента

Після завантаження сторінки сервіс відразу повинен витягувати дані. Для цього ми використовуємо хук життєвого циклу OnInit і викликаємо getPosts. Повний код PostListComponent:

// post-list.component.ts
import { Component, OnInit } from ‘@angular/core’;
import { PostService } from ‘../post.service’;
import { Post } from ‘../Post’;
@Component({
selector: ‘app-post-list’,
template: `

  • {{post.title}}

`,
styleUrls: [‘./post-list.component.scss’]
})
export class PostListComponent implements OnInit {
private posts: Post[] = [];
private errorMessage: any = “;
constructor(private postService: PostService) {}
ngOnInit() {
this.getPosts();
}
getPosts() {
this.postService.getData()
.subscribe(
posts => this.posts = posts,
error => this.errorMessage = error);
}
}

В шаблоні ми з допомогою директиви *ngFor пробегаемся в циклі по posts і друкуємо їх заголовки, интерполируя їх властивість title. Не забувайте, що posts має тип Post, а там ми визначили властивість title. Селектор app-post-list потрібно буде додати на сторінку app.component.html.

// app.component.html

Post Titles

Запустіть в командному рядку ng s –o, щоб запустити додаток на сервері розробки на порту 4200. Опція –o відкриє додаток в браузері за замовчуванням. Після завантаження програми ви повинні побачити список постів на сторінці:

Angular 4 – урок по стороннім API

Якщо ви працюєте в Chrome, можете встановити розширення Augury. З ним дуже зручно працювати з додатками на Angular. Завантажити його можна з магазину Chrome. Натисніть правою кнопкою миші на сторінці і проінспектуйте елемент, щоб відкрити панель розробника. Вкладка Augury буде сама права. Для появи вкладки може знадобитися перезавантаження браузера.

Angular 4 – урок по стороннім API

Зверніть увагу на те, як Augury відображає дерево компонентів ліворуч. Клікнувши на PostListComponent, можна дізнатися поточний стан. У нас є об’єкт posts – масив з 100 постів з властивостями userId, id title і body. Augury дуже зручний при отриманні даних з API із заздалегідь відомою структурою. Наприклад, тепер ми знаємо, що body посту можна відобразити з допомогою {{post.body}}. Репозиторій додатки знайдете на github. Не соромтеся, грайте з ним, спробуйте отримати доступ до різних частин відповіді. Спробуйте переглянути тільки перші 10 заголовків постів. Отримайте доступ до перших трьох заголовків постів з їх body. Сподіваюся, вам сподобалася стаття, і ви дізналися з неї щось нове для себе.