【问题标题】:Angular 'map' operators can't trigger my subscriptionAngular 'map' 操作员无法触发我的订阅
【发布时间】:2020-11-15 07:24:36
【问题描述】:

我使用单个 HTTP 拦截器来解决一些常见的响应。 当响应返回 { success:true, data: 'xxx' } 时,我只想将 'data' 字段传递给订阅 'xxx'。 当我使用“点击”运算符时,我的订阅可能会被触发。但是得到的数据订阅是'{ success : true, data: 'xxx' }'。 所以我决定使用“地图”运算符,但无法触发订阅。 我的 Angular 的版本是 10.0.4,而 rxjs 的版本是 6.5.5。 代码如下,这是我的http拦截器:

import { Code } from '../../../code.enum.js';
import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor,
  HttpResponse,
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { tap, filter, map } from 'rxjs/operators';
import { Router } from '@angular/router';

@Injectable()
export class AppInterceptor implements HttpInterceptor {
  constructor(private router: Router) {}

  intercept(
    request: HttpRequest<unknown>,
    next: HttpHandler
  ): Observable<HttpEvent<unknown>> {
    return next.handle(request).pipe(
      filter((res) => {
        return res.type !== 0;
      }),
      map((res: HttpResponse<{ msg; success; data; code }>) => {
        console.log('[AppInterceptor.intercept.tap] res: %o', res);
        const { msg, success, data, code } = res.body;
        if (success) {
          console.log('[AppInterceptor.intercept.tap] data: %o', data);
          return data;
        }
        if (code === Code.needLogin) {
          this.router.navigateByUrl('/login');
        }
        console.log(msg);
        throw new Error(msg);
      })
    );
  }
}

这是我的登录组件:

import { AppService } from './../app.service';
import { Component, OnInit } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { Validators } from '@angular/forms';
import { Router } from '@angular/router';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss'],
})
export class LoginComponent implements OnInit {
  loginForm = this.fb.group({
    username: ['', Validators.required],
    password: ['', Validators.required],
  });

  constructor(
    private appService: AppService,
    private fb: FormBuilder,
    private router: Router
  ) {}

  ngOnInit(): void {}

  login() {
    if (this.loginForm.valid) {
      const { username, password } = this.loginForm.value;
      this.appService.login(username, password).subscribe((res) => {
        console.log('[LoginComponent.login] res: %o', res);
        this.router.navigateByUrl('/');
      });
      return;
    }
    console.log('nonononono');
  }
}

这是应用服务:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root',
})
export class AppService {

  constructor(private httpClient: HttpClient) {
  }

  login(username, password) {
    return this.httpClient.post('/login', {
      username,
      password,
    });
  }

}

控制台日志,可以看到,代码'console.log('[LoginComponent.login] res: %o', res)'从未运行过,login API的响应数据是{success: true} :

【问题讨论】:

  • 你能 console.log 你的正文内容吗??
  • 对不起,什么是正文内容?我在最后一节中发布,console.log 只显示拦截器中的消息,而不是登录组件。 @AlejandroCamba

标签: angular rxjs


【解决方案1】:

您的拦截器期望返回一个 Observable,除此之外的任何东西都不会通过,请记住,即使它被拦截,它在到达您的组件时仍应保持为 Http 事件。

你可以这样做:

    const evt = { ...res };
    evt.body = evt.body["data"];
    return evt;

返回一个仅包含“数据”属性的事件。

【讨论】:

    猜你喜欢
    • 2021-04-24
    • 2017-03-21
    • 2020-11-19
    • 2021-06-05
    • 2016-10-28
    • 2019-09-22
    • 1970-01-01
    • 2021-07-01
    • 2021-12-23
    相关资源
    最近更新 更多