我有一个简单的登录表单组件(LoginComponent
),该组件调用submitLogin
方法。
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中被打印。
AuthenticationService
看起来(大致)如下:
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
值。顺便说一下,那些控制台日志永远不会发生。
我的API服务负责调用我正在运行的版本化API。其中包含许多无关的内容,但相关的内容是:
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请求。是什么赋予了?它为什么不执行请求,和/或可能导致此错误的原因?
答案 0 :(得分:3)
我在复制代码后进入控制台的stacktrace使我进入Angular的httpClient模块(node_modules\@angular\common\esm5\http\src\headers.js
)的标头代码中的'lazyInit'函数。
在函数的第二行,它迭代您正在提交的标头的值,并且您可以在第三行看到values
变量。在那里,它获取标头之一并访问其值。接下来,将其转换为数组(如果它是字符串),然后检查其长度-此时,您将获得异常。
如果您查看自己的API服务,则要提交两个标头:
'Content-Type': 'application/json',
'Cookie': this.cookies
更早之前,您像这样定义cookies
变量:
private cookies: string;
由于您未分配值,因此默认值为undefined
,该值即为“ Cookie”标头的值,该标头不是字符串,也没有length
属性,因此会引发异常。
解决方案:
将cookies
的初始定义更改为
private cookies = '';
解决此问题。
答案 1 :(得分:0)
如果将任何undefined
传递到HTTP
调用的标头,则可能会发生这种情况,并且如果header
很常见,则可能导致其他调用中断。用默认的空值初始化这些值。此错误消息很难调试。