可观察返回未定义

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 删除了一些代码。您所做的只是重新抛出错误。