Правила     Закладки     Карма    Календарь    Журналы    Помощь    Поиск    PDA    Чат   
        СМС-ки
   
Пейджер выключен!
 
Фильтр авторов:    показать 
  скрыть
  Ответ в темуСоздание новой темыСоздание опроса

> angular 2 + rxjs + http-запросы, застрял на работе с Observable
Invis1ble  
 ۩  [x] Дата
Цитировать сообщение

Пользователя сейчас нет на форуме




******

Профиль
Группа: Эксперт
Группа переписки
Сообщений: 11787
Пользователь №: 23195
На форуме: 6 лет, 4 месяца, 14 дней
Карма: 429

Трезвый :
7 лет, 3 месяца, 14 дней


Изучаю angular 2 и застрял. В гайде написано:
Цитата (https://angular.io/docs/ts/latest/guide/server-communication.html)
While promises may be more familiar, observables have many advantages. Don't rush to promises until you give observables a chance.

В ParentService::getParents() идёт запрос к API, оттуда возвращается json вида:
{
entities: [
{ name: 'parent1', childrenUrl: '/api/parents/parent1/children' },
{ name: 'parent2', childrenUrl: '/api/parents/parent2/children' },
....
]

}

Как правильно с использованием RxJS-Observable пройтись по каждому элементу и сделать запрос по childrenUrl? В .extractData() как-то засунуть эту обработку? Что-то типа response.json().entities.forEach(entity => { this.childService.getChildren(entity.childrenUrl) }) А что возвращать? Короче я застрял в этих RxJS-операторах.

parent.model.ts


import { ChildModel } from './child.model';

export class ParentModel {
name: string;
children: ChildModel[];
}


parent.service.ts

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

import { ChildService } from './child.service';
import { ParentModel } from './parent.model';

@Injectable()
export class ParentService {
private parentsUrl = '/api/parents.json';

constructor(
private http: Http,
private childService: ChildService
) {

}


getParents(): Observable<ParentModel[]> {
return this.http.get(this.parentsUrl)
.
map(this.extractData)
.
catch(this.handleError);
}

private extractData(response: Response) {
return response.json().entities;
}

private handleError(error: any) {
// ...
}
}


child.model.ts

export class ChildModel {
name: string;
}


child.service.ts

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

import { ChildModel } from './child.model';

@Injectable()
export class ChildService {
constructor(private http: Http) {

}


getChildren(childrenUrl): Observable<ChildModel[]> {
return this.http.get(childrenUrl)
.
map(this.extractData)
.
catch(this.handleError);
}

private extractData(response: Response) {
return response.json().entities;
}

private handleError(error: any) {
// ...
}
}


--------------------
PMПисьмо на e-mail пользователюСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Oyeme  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Reality is wrong. Dreams are for real
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 1674
Пользователь №: 16955
На форуме: 7 лет, 9 месяцев, 12 дней
Карма: 94




Цитата
    getChildren(childrenUrl): Observable<ChildModel[]> {
        return this.http.get(childrenUrl)
            .map(this.extractData)
            .catch(this.handleError);
    }


Поподрбней
это массив url? что возрощяет в итоге?


--------------------
Programming: Private lessons via skype £45/h

Частные уроки в Лондоне / удаленно по skype.
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Invis1ble  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме




******

Профиль
Группа: Эксперт
Группа переписки
Сообщений: 11787
Пользователь №: 23195
На форуме: 6 лет, 4 месяца, 14 дней
Карма: 429

Трезвый :
7 лет, 3 месяца, 14 дней


Oyeme
вот компонент, который в итоге получает данные через сервис:

parent-list.component.ts
import { Component, OnInit } from '@angular/core';

import { ParentModel } from './../shared/parent.model';
import { ParentService } from './../shared/parent.service';

@Component({
...
})
export class ParentListComponent implements OnInit {
errorMessage: string;
parents: ParentModel[];

constructor(
private parentService: ParentService
) {

}


ngOnInit() {
this.getParents();
}

getParents() {
this.parentService
.getParents()
.
subscribe(
parents => this.parents = parents,
error => this.errorMessage = error
);
}
}


--------------------
PMПисьмо на e-mail пользователюСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Invis1ble  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме




******

Профиль
Группа: Эксперт
Группа переписки
Сообщений: 11787
Пользователь №: 23195
На форуме: 6 лет, 4 месяца, 14 дней
Карма: 429

Трезвый :
7 лет, 3 месяца, 14 дней


то есть я получаю с сервера коллекцию сущностей, у каждой из этой сущности есть массив дочерних сущностей
но дочерние не подгружаются при первом запросе, а вместо этого для каждой сущности в первом ответе содержится endpoint для получения соответствующей коллекции дочерних сущностей
нужно после первого ответа подгрузить для каждой сущности массив их дочерних сущностей


--------------------
PMПисьмо на e-mail пользователюСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Oyeme  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Reality is wrong. Dreams are for real
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 1674
Пользователь №: 16955
На форуме: 7 лет, 9 месяцев, 12 дней
Карма: 94




Цитата
А что возвращать? Короче я застрял в этих RxJS-операторах.

Я бы немного переделал логику построения.

В идеале Вам нужно сделать что-то типо дерева.Даже если children не будут иметь детей.

Что каждые элемента parent либо children одного и того же класса.
В Вашем примере вы возрощяете например export class Tree {}

Потом у Вас есть метода как loadChildren()которой пробегает по всей коллекции и загружает в stack элементы того же класса Tree();

У Вас получится что-то типо такого
Root Tree -> Children:
Element1
-- ChildA
-- ChildB
Element2
-- ChildA
-- ChildB

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






--------------------
Programming: Private lessons via skype £45/h

Частные уроки в Лондоне / удаленно по skype.
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Invis1ble  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме




******

Профиль
Группа: Эксперт
Группа переписки
Сообщений: 11787
Пользователь №: 23195
На форуме: 6 лет, 4 месяца, 14 дней
Карма: 429

Трезвый :
7 лет, 3 месяца, 14 дней


Oyeme
Зачем здесь дерево? У меня всего один уровень вложенности, обычная связь one-to-many. Например пользователь и его комментарии.
Я подгрузил список пользователей, теперь нужно пройтись по этому списку и для каждого пользователя подгрузить его комментарии.
Тебя наверное просто сбили с толку названия ParentModel и ChildModel. Замени их мысленно на UserModel и CommentModel.


--------------------
PMПисьмо на e-mail пользователюСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Oyeme  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Reality is wrong. Dreams are for real
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 1674
Пользователь №: 16955
На форуме: 7 лет, 9 месяцев, 12 дней
Карма: 94




Цитата
Что-то типа response.json().entities.forEach(entity => { this.childService.getChildren(entity.childrenUrl) }) А что возвращать? Короче я застрял в этих RxJS-операторах.

Не нравится мне запросы в запросах.От этого сложно проводить debugging.

Вот у тебя есть Collections of Users и вызываешь метод который пробегает по всем моделям и загружает для каждой модельки comments.
А не вызывать запрос в запросе после получения первой сущности.

Users.loadComments();
И потом что-то типо такого.
that= this;
angular.forEach(UserCollections., function(userModel, key) {
userModel.loadComments();
}, users);


В loadComments() у нас идут типо

 loadComments(): Observable<CommentModel[]> {
return this.http.get(this.parentsUrl)
.
map(this.extractData)
.
subscribe(res => {
//data manipulation
that.comments = res;

}).catch(this.handleError);
}



Это просто пример с набросками
that - parent of this.


--------------------
Programming: Private lessons via skype £45/h

Частные уроки в Лондоне / удаленно по skype.
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Zzepish  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Аццкая хрень
******

Профиль
Группа: ★ЛжеЭксперт★
Завсегдатай форума
Сообщений: 5475
Пользователь №: 32538
На форуме: 4 года, 6 месяцев, 11 дней
Карма: 49




Второй ангуляр более низкоуровневый, чем первый?


--------------------
Правда тоже ложь, но с иным углом.
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Invis1ble  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме




******

Профиль
Группа: Эксперт
Группа переписки
Сообщений: 11787
Пользователь №: 23195
На форуме: 6 лет, 4 месяца, 14 дней
Карма: 429

Трезвый :
7 лет, 3 месяца, 14 дней


Zzepish
он другой




--------------------
PMПисьмо на e-mail пользователюСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Invis1ble  
 ۩  [x] Дата
Цитировать сообщение

Пользователя сейчас нет на форуме




******

Профиль
Группа: Эксперт
Группа переписки
Сообщений: 11787
Пользователь №: 23195
На форуме: 6 лет, 4 месяца, 14 дней
Карма: 429

Трезвый :
7 лет, 3 месяца, 14 дней


Oyeme
Цитата (Oyeme @ 27.06.2016 - 17:03)
Вот у тебя есть Collections of Users и вызываешь метод который пробегает по всем моделям и загружает для каждой модельки comments.

тогда модель UserModel будет только частично наполнена данными, я не хочу чтобы consumer этого сервиса (UserService) должен был заботиться о наполнении данных. Он должен получать уже полностью гидрированные данные. ИМХО, конечно.

Вот так на данный момент получилось у меня:
user.service.ts
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/from';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/toArray';
import 'rxjs/add/operator/toPromise';

import { CommentService } from './comment.service';
import { UserModel } from './user.model';

@Injectable()
export class UserService {
private usersUrl = '/api/users';

constructor(
private http: Http,
private commentService: CommentService
) {

}


getUsers(): Observable<UserModel[]> {
return this.http.get(this.usersUrl)
.
map(this.extractData)
.
mergeMap((users) => this.hydrateData(users))
.
catch(this.handleError);
}

private extractData(response: Response) {
return response.json().entities;
}

private hydrateData(users) {
return Observable.from(users)
.
mergeMap((user: any) => {
return this.commentService
.getComments(user._links.comments.href)
.
toPromise()
.
then((comments) => {
user.comments = comments;
return user;
});
})
.
toArray();
}

private handleError(error: any) {
// ...
}
}

не уверен, правильно ли. Написал на основе вот этого вопроса: http://stackoverflow.com/q/29735456/1636505


--------------------
PMПисьмо на e-mail пользователюСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Invis1ble  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме




******

Профиль
Группа: Эксперт
Группа переписки
Сообщений: 11787
Пользователь №: 23195
На форуме: 6 лет, 4 месяца, 14 дней
Карма: 429

Трезвый :
7 лет, 3 месяца, 14 дней


избавился от промисов
    private hydrateData(users) {
return Observable.from(users)
.
mergeMap((user: any) => {
return this.commentService
.getComments(user._links.comments.href)
.
map((comments) => {
user.comments = comments;
return user;
});
})
.
toArray();
}


--------------------
PMПисьмо на e-mail пользователюСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
  Быстрый ответ
Информация о Госте
Введите Ваше имя
Кнопки кодов
Для вставки цитаты, выделите нужный текст и
НАЖМИТЕ СЮДА
Введите сообщение
Смайлики
:huh:  :o  ;) 
:P  :D  :lol: 
B)  :rolleyes:  <_< 
:)  :angry:  :( 
:unsure:  :blink:  :ph34r: 
     
Показать всё

Опции сообщения  Включить смайлики?
 Включить подпись?
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:

Опции темы Ответ в темуСоздание новой темыСоздание опроса