Передать первый элемент подписанных данных в сервис - PullRequest
0 голосов
/ 01 мая 2018

Я разрабатываю угловое приложение, где мне нужно применить следующий механизм:

Мое представление состоит из 2 частей (список элементов и подробности, если выбран элемент). Пользователь может щелкнуть по некоторому элементу, и следующий сервис извлечет дополнительные данные для этого элемента и отобразит их в подробном представлении. Также я хочу выбрать первый элемент автоматически при запуске, если доступно.

Вот мой сервис:

@Injectable()
export class ItemService {

  private url: string;
  private itemSource = new BehaviorSubject<Item>(null);
  selectedItem = this.itemSource.asObservable();

  constructor(private http: HttpClient) {
    this.url = 'http://localhost:8080/api/item';
  }

  getItems(): Observable<Item[]> {
    let observable = this.http.get<Item[]>(this.url)
      .map(items => items.map(item => {
        return new Item(item);
      }));
    return observable;
  }

  selectItem(item: Item) {
    return this.http.get<Item>(this.url + '/' + item.id)
      .map(item => new Item(item))
      .subscribe(t => this.itemSource.next(t));
  }
}

подробно компонент Я подписываюсь выбранный пункт, как это:

  ngOnInit() {
    this.itemService.selectedItem.subscribe(item => this.selectedItem = item);
  }

и следующий код взят из моего компонента, где я отображал список элементов. Я также хочу установить выбранный элемент после подписки данных, но мой код не работает. Я перебираю свойство items [] в html-шаблоне, и данные отображаются, но когда я получаю доступ к этому массиву после того, как я подписан на данные, я получаю неопределенное значение. Можете ли вы исправить мой код? Спасибо!

  public items = [];

  constructor(private itemService: ItemService) { }

  ngOnInit() {
    this.itemService.getItems()
      .subscribe(
        data => this.items = data,
        err => console.log(err),
        function () {
          console.log('selected data', this.items); // this prints undefined
          if (this.items && this.items.length) {
            this.itemService.selectedItem(this.items[0])
          }
        });
  }

1 Ответ

0 голосов
/ 01 мая 2018

Ваша проблема в том, что вы не используете функцию стрелки для обратного вызова complete при вызове subscribe. Как видите, вы используете функции стрелок для next и error.

Когда вы определяете новую функцию с помощью function(...) {...}, вы создаете новый контекст, и поэтому ключевое слово this меняет свое значение. Разница между функцией стрелки и обычными функциями (на мой взгляд, помимо того, что она более элегантна) состоит в том, что функции стрелки не определяют новый контекст для this, и поэтому значение этого ключевого слова такое же, как и в контексте, в котором они находятся. определены. Таким образом, в ваших обратных вызовах next и error, this является вашим компонентом, но в вашем вызове complete, this, скорее всего, является ссылкой на window, которая не имеет items свойство, следовательно, undefined.

Измените свой код на:

public items = [];

constructor(private itemService: ItemService) { }

ngOnInit() {
  this.itemService.getItems()
  .subscribe(
    data => this.items = data,
    err => console.log(err),
    () => {
      console.log('selected data', this.items); // this prints undefined
      if (this.items && this.items.length) {
        this.itemService.selectedItem(this.items[0])
      }
    });
}

Я полагаю, вы использовали ключевое слово function, потому что у этой функции не было аргументов, но вы можете выразить это с помощью синтаксиса () => expression или () => {...}

data => this.items = data, в конце концов, это более простой и элегантный способ написания

(data) => { return this.items = data; }
...