Angular 9 - как вставить динамические параметры в конструктор службы

Мне нужно сделать запросы к URL-адресу серверной части, который имеет следующую форму:

localhost:8000/myapp/item1/:id1/item2/:id2/item3

где id1 и id2 - динамические числа. Я думал использовать службу, которая принимает в конструкторе 2 аргумента, что-то вроде этого

export class Item3Service {

  private id1: number;
  private id2: number;

  constructor(
    id1: number,
    id2: number
  ) {
    this.id1 = id1;
    this.id2 = id2;
  }

  getList() {/**** implementation here ****/}
  getDetail(id3: number) {/**** implementation here ****/}
  create() {/**** implementation here ****/}
  update(id3: number) {/**** implementation here ****/}
  delete(id3: number) {/**** implementation here ****/}

}

Я действительно не знаю, как вставлять параметры в конструктор. Мне также нужно использовать эту службу внутри преобразователя, и опять же, как я могу передать ему параметры в преобразователе? Создание токена внедрения в этом случае кажется бесполезным, потому что значение токена должно каждый раз меняться. У меня закончились идеи


person dc_Bita98    schedule 11.08.2020    source источник
comment
Значит, вы в основном хотите, чтобы значение id1 и id2 в сервисе было правильным?   -  person Kamran Khatti    schedule 11.08.2020
comment
Да, и эти значения должны быть изменены во время выполнения   -  person dc_Bita98    schedule 12.08.2020


Ответы (2)


Лучше, если ваша Служба не будет иметь состояния, это снизит сложность вашего приложения и избавит вас от некоторых проблем и отладки, и в этом просто нет необходимости, потому что вы всегда можете получить item1Id и item2Id из вашего активированного маршрута, поэтому позвольте активированному маршруту удерживать состояние вашего приложения (в этом случае состояние - это то, что выбраны Item1Id и Item2Id) и создайте службу без отслеживания состояния, которую вы можете вызывать из любого места и которая содержит логика вашего Item API.

Вот как я представляю себе ваш сервис (имейте в виду, что это всего лишь пример, который нужно принять во внимание, поскольку я точно не знаю вашу семантику и варианты использования)

ItemService

export class ItemService {
  constructor(private http: HttpClient) {}

  getList(item1Id: string, item2Id: string) {
    /* Call to Get List endpoint with Item1Id and Item2Id */
  }

  getDetails(item1: string, item2: string, item3: string) {
    /* Call to Get Details endpoint with Item1Id and Item2Id and Item3Id */
  }
}

Затем вы можете использовать эту службу везде, если у вас есть доступ к ActivatedRouteSnapshot или ActivatedRoute.

Пример использования в Resolver для маршрута item1 /: item1Id / item2 /: item2Id

export class ItemResolver implements Resolve<any> {
  constructor(private itemService: ItemService) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<any> {
    return this.itemService.getList(route.params['item1Id'], route.params['item2Id']);
  }
}

Пример использования в компоненте для маршрута item1 /: item1Id / item2 /: item2Id для получения сведений об элементе 3

export class HelloComponent  {

  constructor(private route: ActivatedRoute, private itemService: ItemService) {}

  getDetails(item3Id) {
    this.route.params.pipe(
      take(1),
      map(({ item1Id, item2Id }) => {
        console.log(this.itemService.getDetails(item1Id, item2Id, item3Id))
      })
    ).subscribe();
  }
}

Вот рабочий StackBlitz, демонстрирующий это: https://stackblitz.com/edit/angular-ivy-h4nszy

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

person h0ss    schedule 11.08.2020
comment
Ты прав. Я упустил суть и пытался нести нежелательные заботы о своем сервисе. В моем проекте мне, наверное, понадобятся 2, если не 3 услуги такого типа. поэтому я собираюсь создать базовый параметризованный класс обслуживания, который может принимать переменное количество параметров для каждого из своих методов, и он сможет создать правильный URL-адрес для запроса серверной части - person dc_Bita98; 12.08.2020

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

Услуга

export class Item3Service {

  constructor(
    @inject(LOCALE_ID) private locale: string) {}

}

app.moudle.ts

@NgModule({
  providers: [
    { provide: LOCALE_ID, useFactory: () => window.navigator.language}
  ]
})

Редактировать

Поскольку идентификаторы являются частью вашего маршрута, я бы сделал это так

Составная часть

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { MyServiceService } from '../my-service.service';

@Component({
  selector: 'app-routed',
  templateUrl: './routed.component.html',
  styleUrls: ['./routed.component.scss']
})
export class RoutedComponent implements OnInit {

  constructor(private route: Router, private myService: MyServiceService) { }

  ngOnInit(): void {
    this.myService.setUrl(this.route.url)
  }

}

Услуга

import { Injectable } from '@angular/core';
import { ReplaySubject, Observable } from 'rxjs';
import { share, switchMap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class MyServiceService {
  private _url$: ReplaySubject<string> = new ReplaySubject<string>(1);

  private _mydata$: Observable<string>;
  get myData$() { return this._mydata$.pipe(share()); }


  constructor() {
    this._mydata$ = this._url$.pipe(
      switchMap(url => {
        const parsedUrl = this.parseUrl(url);
        return this.callBackend(parsedUrl)
      })
    )
  }

  setUrl(url: string) {
    this._url$.next(url);
  }

  private callBackend(parsedUrl): Observable<string> {
    // call backend 
  }

  private parseUrl(url: string): number[] {
    // parse ids
  }
}

person Bertramp    schedule 11.08.2020
comment
Я не знаю, откуда вы берете динамические идентификаторы - ›вот проблема, потому что эти идентификаторы должны меняться во время выполнения. Они представляют собой первичный ключ некоторой модели в серверной базе данных. Они будут частью запрашиваемого URL. Я действительно не знаю, как с ними бороться. Возможно, единственное возможное решение - это рефакторинг и передача их в качестве параметров через каждый метод службы. Но это звучит громоздко - person dc_Bita98; 11.08.2020
comment
Я не совсем понимаю, где хранятся / генерируются идентификаторы? - person Bertramp; 11.08.2020
comment
На самом деле я разбираю идентификаторы с URL-адреса. Например, пользователь находится на странице / item1 / 1 / item2 / 1. Он хочет создать item3, который принадлежит item2. Служба будет создана с идентификаторами id1 = 1 и id2 = 1, переданными в его конструктор. Затем служба отправит запрос POST на внутренний URL-адрес / item1 / 1 / item2 / 1 / item3 /. - person dc_Bita98; 11.08.2020
comment
Понятно. Затем вы должны получить их от роутера, а затем просто создать в сервисе метод их настройки. - person Bertramp; 11.08.2020
comment
Спасибо, сэр. На самом деле я имел в виду именно это. С другой стороны, я призываю всех, кто приходит сюда, прочитать ответ @ h0ss. С точки зрения разработки программного обеспечения для службы лучше не иметь состояния. Задача сервиса - предоставить данные из бэкэнда, это не его забота о сохранении информации о текущем URL-адресе страницы пользователя. - person dc_Bita98; 12.08.2020
comment
В этом случае да, лучше, чтобы служба не имела гражданства. Но как общее утверждение это очень неверно. Сервисы как управление состоянием имеют множество допустимых вариантов использования - person Bertramp; 12.08.2020
comment
@Bertramp Согласен, есть много вариантов использования, в которых это может понадобиться, но чаще всего лучше отделить государственные службы от служб бизнес-логики. - person h0ss; 13.08.2020