角“值未定义"订阅映射的HTTP响应(是否未发出请求?) [英] Angular 'values is undefined' subscribing to mapped http response (request not being made?)

查看:85
本文介绍了角“值未定义"订阅映射的HTTP响应(是否未发出请求?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的登录表单组件(LoginComponent),该组件调用submitLogin方法.

I have a simple login form component (LoginComponent) that calls the submitLogin method.

import { Component, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Router, ActivatedRoute } from '@angular/router';
import { first }  from 'rxjs/operators';

import { AuthenticationService } from '../../services';

@Component({
    selector: 'login',
    templateUrl: './login.component.html',
    styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
    returnURL: string;

    u = new FormControl('');
    p = new FormControl('');

    constructor(private route: ActivatedRoute, private router: Router, private auth: AuthenticationService) { }

    ngOnInit() {
        this.returnURL = this.route.snapshot.queryParams['returnUrl'] || '/';
    }

    submitLogin(): void {
        this.auth.login(this.u.value, this.p.value).pipe(first()).subscribe(
            r => {
                if (r) {
                    console.log("LoginComponent: r:", r);
                    this.router.navigate([this.returnURL]);
                }
            },
            error => {
                console.error("LoginComponent: Error:", error);
            }
        );
    }

}

我得到的错误被打印为LoginComponent: Error: TypeError: 'values' is undefined,并且在该错误lambda中被打印.

The error I'm getting is getting printed as LoginComponent: Error: TypeError: 'values' is undefined, and it's getting printed in that error lambda.

AuthenticationService看起来(大致)如下:

The AuthenticationService looks (roughly) like this:

import { Injectable } from '@angular/core';
import { HttpClient, HttpResponse } from '@angular/common/http';
import { BehaviorSubject, Observable } from 'rxjs';
import { map } from 'rxjs/operators';

import { User } from '../models/user';
import { APIService } from './api.service';

@Injectable({ providedIn: 'root' })
export class AuthenticationService {
    private currentUserSubject: BehaviorSubject<User>;
    public currentUser: Observable<User>;

    constructor(private http: HttpClient, private api: APIService) {
        this.currentUserSubject = new BehaviorSubject<User>(null);
        this.currentUser = this.currentUserSubject.asObservable();
    }
    login(u: string, p: string): Observable<boolean> {
        return this.api.login(u, p).pipe(map(
            r => {
                if (r && r.status === 200) {
                    this.updateCurrentUser();
                    console.log("returning true");
                    return true;
                }
                console.log("returning false");
                return false;
            }
        ));
    }
}

请注意,映射lambda中的所有代码路径均返回布尔值.因此,此映射永远不要吐出undefined值.顺便说一下,那些控制台日志永远不会发生.

Notice that all code paths in the map lambda return a boolean value. So this map should never spit out undefined values. Those console logs never happen, by the way.

我的API服务负责对我正在运行的版本化API进行调用.其中包含许多无关的内容,但相关的内容是:

And my API service is responsible for making calls to a versioned API I have running. It's got a lot of unrelated stuff in it, but the relevant bits are:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http';
import { BehaviorSubject, Observable } from 'rxjs';
import { map, first } from 'rxjs/operators';

@Injectable({ providedIn: 'root' })
export class APIService {
    public API_VERSION = '1.5';

    private cookies: string;

    constructor(private http: HttpClient) {}

    private do(method: string, path: string, data?: Object): Observable<HttpResponse<any>> {
        const options = {headers: new HttpHeaders({'Content-Type': 'application/json',
                                                   'Cookie': this.cookies}),
                         observe: 'response' as 'response',
                         body: data};
        return this.http.request(method, path, options).pipe(map(r => {
            //TODO pass alerts to the alert service
            let resp = r as HttpResponse<any>;
            if ('Cookie' in resp.headers) {
                this.cookies = resp.headers['Cookie']
            }
            console.log("returning resp");
            return resp;
        }));
    }

    public login(u, p): Observable<HttpResponse<any>> {
        const path = '/api/'+this.API_VERSION+'/user/login';
        return this.do('post', path, {u, p});
    }
}

请再次注意,映射lambda中的每个代码路径都会返回一个值.另请注意,"returning resp"永远不会出现在控制台中.我也从未在网络面板中看到HTTP请求.是什么赋予了?它为什么不执行请求,和/或可能导致此错误的原因?

Note that again, every code path in the map lambda returns a value. Also note that "returning resp" never appears in the console. I also never see an HTTP request being made in the network panel. What gives? Why isn't it doing the request, and/or what could possibly be causing this error?

推荐答案

复制代码后,我在控制台中获得的stacktrace使我进入Angular的httpClient模块(node_modules\@angular\common\esm5\http\src\headers.js)的标头代码中的'lazyInit'函数.

The stacktrace I got in the console after replicating your code led me to the 'lazyInit' function within the headers code of Angular's httpClient module (node_modules\@angular\common\esm5\http\src\headers.js).

在函数的第二行中,它遍历正在提交的标头的值,并且您可以在第三行看到values变量.在那里,它获取标题之一并访问其值.接下来,将其转换为数组(如果是字符串),然后检查其长度-此时,您将获得异常.

In the second line of the function, it iterates over the values of the header you're submitting, and you can see the values variable on the third. There it gets one of the headers and accesses it's values. Next it converts it to an array, if it's a string, and then checks it's length - at this point you get the exception.

如果您查看自己的API服务,则要提交两个标头:

If you look at your API service, there's two headers you're submitting:

'Content-Type': 'application/json',
'Cookie': this.cookies

更早之前,您可以这样定义cookies变量:

And earlier, you define the cookies variable like this:

private cookies: string;

由于您未分配值,因此默认值为undefined,这就是您的"Cookie"标头的值,该标头不是字符串,也不具有length属性,因此它是引发异常.

Since you don't assign a value, it defaults to undefined, which is then the value of your 'Cookie' header, which is not a string and also doesn't have a length property, so it's throwing an Exception.

解决方案:

cookies的初始定义更改为

private cookies = '';

解决此问题.

这篇关于角“值未定义"订阅映射的HTTP响应(是否未发出请求?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆