可观察返回未定义
Oberservable returning undefined
我在登录用户时遇到问题。我正在使用的是带有 rails 5 api 运行 devise_token_auth 的 nativescript-angular 进行身份验证。真正奇怪的是,在服务器日志中,它显示请求已完成并返回 200 状态。此外,似乎 observable 本身或 map 函数 returns 未定义,我不确定为什么。如果有人能看一下那就太棒了。
auth.service.ts
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'
import { Response, Http, Headers, RequestOptions, } from '@angular/http'
import * as Toast from 'nativescript-toast'
// import 'rxjs/add/operator/map'
// import 'rxjs/add/operator/catch'
// import 'rxjs/add/Observable/throw'
@Injectable()
export class AuthService {
constructor(private http: Http) {}
signinUser(signInData: { email: string, password: string }): Observable<Response> {
let headers = new Headers;
headers.append('Content-Type', 'application/json')
let options = new RequestOptions({ headers: headers })
let url = 'backend api'
return this.http.post(url, signInData, options)
.map((res: Response) => {
let body = res.json()
console.log("body: " + body)
console.log('status: ' + res.json().status)
Toast.makeText('status: ' + res.json().status).show();
console.log('statusText: ' + res.json().statusText)
Toast.makeText('statusText: ' + res.json().statusText).show();
return body || null
})
.catch((error) => {
return Observable.throw(error)
})
}
}
signin.component.ts
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Rx'
import { Router, NavigationExtras } from '@angular/router'
import { FormGroup, FormControl, Validators, AbstractControl, FormBuilder } from '@angular/forms'
import { Http, Headers, RequestOptions, Response } from '@angular/http'
import { AuthService } from '../auth/auth.service'
import * as Toast from "nativescript-toast";
@Component({
moduleId: module.id,
selector: 'app-signin',
templateUrl: './signin.component.html',
styleUrls: ['./signin.component.css']
})
export class SigninComponent implements OnInit {
signinForm: FormGroup;
constructor(private router: Router,
private http: Http,
private fb: FormBuilder,
private authService: AuthService) {}
ngOnInit() {
this.signinForm = this.fb.group({
'email': new FormControl(null, [Validators.required, Validators.email,
Validators.pattern("[a-zA-Z0-9.-_]{1,}@[a-zA-Z.-]{2,}[.]{1}[a-zA-Z]{2,}")]),
'password': new FormControl(null, Validators.required)
})
}
onSignin(form: any) {
const email = form.email
const password = form.password
this.authService.signinUser({ email, password })
.subscribe(
(res) => {
if(res.statusText == 'OK') {
this.router.navigate(['movies'])
} else {
console.log(res.status + ' FAILURE')
Toast.makeText(res.status + ' FAILURE').show();
}
},
(error) => {
Toast.makeText(error.message).show();
},
() => {
console.log('IN SUBSCRIBE')
Toast.makeText('IN SUBSCRIBE').show();
}
)
}
}
编辑 1
控制台内容如下
JS: body: [object Object]
JS: status: undefined
JS: statusText: undefined
JS: undefined FAILURE
JS: IN SUBSCRIBE
事情是这样的:
当您对响应调用 .json() 时,它会获取响应的主体并在其上调用 JSON.parse() 并将该值 returns 提供给您。所以诸如响应状态和 statusText 之类的东西不在您从 json() 返回的值中,只有实际的 json 响应主体在那里。
如果你想访问这些东西,只需在你的服务中直接从响应对象中获取它们,就像这样:
return this.http.post(url, signInData, options)
.map((res: Response) => {
let body = res.json()
console.log("body: " + body)
console.log('status: ' + res.status)
Toast.makeText('status: ' + res.status).show();
console.log('statusText: ' + res.statusText)
Toast.makeText('statusText: ' + res.statusText).show();
return body || null
})
.catch((error) => {
return Observable.throw(error)
})
}
至于在您的组件中,您应该构建它,以便您的组件不需要关心诸如响应状态之类的事情。这是一个服务级别的任务,如果它不是它需要的,那么使用 Observable.throw() 来确保它进入组件错误处理程序。值得一提的是,如果 http 服务收到任何类型的错误响应,它无论如何都会转到错误处理程序,而无需您进行干预。
还有这篇:
.catch((error) => {
return Observable.throw(error)
})
完全没有意义,除非你为了 SO 删除了一些代码。您所做的只是重新抛出错误。
我在登录用户时遇到问题。我正在使用的是带有 rails 5 api 运行 devise_token_auth 的 nativescript-angular 进行身份验证。真正奇怪的是,在服务器日志中,它显示请求已完成并返回 200 状态。此外,似乎 observable 本身或 map 函数 returns 未定义,我不确定为什么。如果有人能看一下那就太棒了。
auth.service.ts
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'
import { Response, Http, Headers, RequestOptions, } from '@angular/http'
import * as Toast from 'nativescript-toast'
// import 'rxjs/add/operator/map'
// import 'rxjs/add/operator/catch'
// import 'rxjs/add/Observable/throw'
@Injectable()
export class AuthService {
constructor(private http: Http) {}
signinUser(signInData: { email: string, password: string }): Observable<Response> {
let headers = new Headers;
headers.append('Content-Type', 'application/json')
let options = new RequestOptions({ headers: headers })
let url = 'backend api'
return this.http.post(url, signInData, options)
.map((res: Response) => {
let body = res.json()
console.log("body: " + body)
console.log('status: ' + res.json().status)
Toast.makeText('status: ' + res.json().status).show();
console.log('statusText: ' + res.json().statusText)
Toast.makeText('statusText: ' + res.json().statusText).show();
return body || null
})
.catch((error) => {
return Observable.throw(error)
})
}
}
signin.component.ts
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Rx'
import { Router, NavigationExtras } from '@angular/router'
import { FormGroup, FormControl, Validators, AbstractControl, FormBuilder } from '@angular/forms'
import { Http, Headers, RequestOptions, Response } from '@angular/http'
import { AuthService } from '../auth/auth.service'
import * as Toast from "nativescript-toast";
@Component({
moduleId: module.id,
selector: 'app-signin',
templateUrl: './signin.component.html',
styleUrls: ['./signin.component.css']
})
export class SigninComponent implements OnInit {
signinForm: FormGroup;
constructor(private router: Router,
private http: Http,
private fb: FormBuilder,
private authService: AuthService) {}
ngOnInit() {
this.signinForm = this.fb.group({
'email': new FormControl(null, [Validators.required, Validators.email,
Validators.pattern("[a-zA-Z0-9.-_]{1,}@[a-zA-Z.-]{2,}[.]{1}[a-zA-Z]{2,}")]),
'password': new FormControl(null, Validators.required)
})
}
onSignin(form: any) {
const email = form.email
const password = form.password
this.authService.signinUser({ email, password })
.subscribe(
(res) => {
if(res.statusText == 'OK') {
this.router.navigate(['movies'])
} else {
console.log(res.status + ' FAILURE')
Toast.makeText(res.status + ' FAILURE').show();
}
},
(error) => {
Toast.makeText(error.message).show();
},
() => {
console.log('IN SUBSCRIBE')
Toast.makeText('IN SUBSCRIBE').show();
}
)
}
}
编辑 1
控制台内容如下
JS: body: [object Object]
JS: status: undefined
JS: statusText: undefined
JS: undefined FAILURE
JS: IN SUBSCRIBE
事情是这样的:
当您对响应调用 .json() 时,它会获取响应的主体并在其上调用 JSON.parse() 并将该值 returns 提供给您。所以诸如响应状态和 statusText 之类的东西不在您从 json() 返回的值中,只有实际的 json 响应主体在那里。
如果你想访问这些东西,只需在你的服务中直接从响应对象中获取它们,就像这样:
return this.http.post(url, signInData, options)
.map((res: Response) => {
let body = res.json()
console.log("body: " + body)
console.log('status: ' + res.status)
Toast.makeText('status: ' + res.status).show();
console.log('statusText: ' + res.statusText)
Toast.makeText('statusText: ' + res.statusText).show();
return body || null
})
.catch((error) => {
return Observable.throw(error)
})
}
至于在您的组件中,您应该构建它,以便您的组件不需要关心诸如响应状态之类的事情。这是一个服务级别的任务,如果它不是它需要的,那么使用 Observable.throw() 来确保它进入组件错误处理程序。值得一提的是,如果 http 服务收到任何类型的错误响应,它无论如何都会转到错误处理程序,而无需您进行干预。
还有这篇:
.catch((error) => {
return Observable.throw(error)
})
完全没有意义,除非你为了 SO 删除了一些代码。您所做的只是重新抛出错误。