Частичная наблюдаемая обработка в Angular 2

У меня есть компонент, который представляет собой форму входа: loginForm, которая вызывает мой API:

  onLogin(): void {

    let username = this.loginForm.value.username;
    let password = this.loginForm.value.password;

    this.api.login(username, password);

      .map(res => res.json())

      .subscribe(
        this._processData,
      );

  }

Есть служба, которая вызывает API: loginService.

login(username: string, password: string): Subscription<any> {

    let headers = new Headers();
    headers.append("Content-Type", "application/json");

    return this.http.put("https://myapi.com", JSON.stringify({ username: username, password: password}), {
      headers: headers
    })

    .map(res => res.json())

    .subscribe(
      data => console.log(data),
      err => console.log(err),
      () => console.log("Done")
    );

}

Я хочу, чтобы ошибка обрабатывалась внутри loginService. Но результат обратно к методу onLogin.

Я пробовал различные обработчики сопоставления (как показано) в onLogin, но не смог заставить их работать. Любые мысли о том, что я могу сделать неправильно?


person Bas van Dijk    schedule 21.01.2016    source источник
comment
Во-первых, удалите ; перед вызовом .map() в this.api.login(username, password);, иначе вы его не вызываете. Во-вторых, не сопоставляйте дважды, вы уже определили сопоставитель для наблюдаемого в сервисе. В-третьих, вторая подписка, которую вы выполняете (та, что в контроллере), неверна, используйте тот же синтаксис, который вы использовали в службе: .subscribe( data => this.data = data );   -  person Langley    schedule 21.01.2016


Ответы (2)


Фактически, вы определяете обратный вызов в методе subscribe для обработки ошибок в методе login (второй параметр). Если вы хотите, чтобы ошибки распространялись на ваш метод onLogin, вам нужно удалить этот обратный вызов (и даже вызов subscribe).

return this.http.put("https://myapi.com",
  JSON.stringify({ username: username, password: password}), {
    headers: headers
  })
.map(res => res.json());

Если вы хотите зарегистрировать ошибку, а затем распространить ее, вы можете использовать метод Observable.throw:

return this.http.put("https://myapi.com",
  JSON.stringify({ username: username, password: password}), {
    headers: headers
  })

.map(res => res.json())

.catch(err => {
  console.log(err);
  return Observable.throw(err);
});

В этом случае вам нужно добавить обратный вызов для обработки ошибки в методе onLogin:

onLogin(): void {
  let username = this.loginForm.value.username;
  let password = this.loginForm.value.password;

  this.api.login(username, password)
  .subscribe(
    (data) => {
      // Success
      this._processData(data)
    },
    (err) => {
      // Error
    }
  );
}

Вы можете заметить, что в Observable есть оператор catch для перехвата ошибок, а в случае ошибок оператор map не вызывается.

Эти ответы могут дать вам более подробную информацию:

Надеюсь, это поможет вам, Тьерри.

person Thierry Templier    schedule 21.01.2016
comment
Спасибо за Ваш ответ! В строке с this.api.login(username, password) .subscribe( я получаю сообщение об ошибке, говорящее о том, что «подписаться» не существует для типа subscription<any> - person Bas van Dijk; 22.01.2016
comment
Я забыл сказать, что это подписка в моей функции входа (). Похоже, вы не можете подписаться на обе функции или что-то в этом роде. - person Bas van Dijk; 22.01.2016
comment
Да, ты прав! Я сделал ошибку в своем ответе. Вам нужно вернуть Observable.throw(err);... Я обновил свой код. Теперь должно быть лучше ;-) - person Thierry Templier; 22.01.2016
comment
Теперь я получаю ошибку property 'subscribe' does not exist on type 'void' - person Bas van Dijk; 22.01.2016
comment
Странно, теперь я очистил все мои сгенерированные файлы .js, он снова выдает предыдущую ошибку subscribe, не существующую на Subscription<any> - person Bas van Dijk; 22.01.2016
comment
Хм странно! Я создал plunkr, чтобы увидеть, что я имею в виду: plnkr.co/edit/rsJXelOYshVVBwyUJNIz?p= предварительный просмотр ;-) - person Thierry Templier; 22.01.2016
comment
Оно работает. В вашем примере выше catch отсутствует вокруг return Observable.throw(err.json());. Спасибо за ваши усилия! - person Bas van Dijk; 22.01.2016
comment
Давайте продолжим обсуждение в чате. - person Bas van Dijk; 22.01.2016

Вы можете определить свой обработчик ошибок в своей службе и просто передать ошибку из компонента, на который вы подписаны.

// component

onLogin(): void {

let username = this.loginForm.value.username;
let password = this.loginForm.value.password;

this.api
  .login(username, password)
  .subscribe(
    this._processData, // success
    this.api.onError   // error
    // if above doesn't work this should:
    // error => this.api.onError(error)
  );

}

_processData(...data) { console.log(data); }

// service

login(username: string, password: string): Subscription<any> {

  let headers = new Headers();
  headers.append("Content-Type", "application/json");

  return this.http
    .put("https://myapi.com", JSON.stringify({ username: username, password: password}), { headers: headers })
    .map(res => res.json())
}

onError(...args) { console.log(args); }
person Sasxa    schedule 21.01.2016