Angular 5 HTTP响应未定义

时间:2018-04-06 12:45:22

标签: angular http undefined observable response

我正在开发一个带有angular和nodejs和express的小型全栈项目。我有一个问题,我在dataservice中的一个方法没有返回数据并调试它,它说明返回值是未定义的。

//客户端

Clubs.ts

export interface Clubs {
  id?: number;
  club_name: string;
  specific_category_id?: number;
  club_category_id?: number;
  county_id?: number;
}

APP-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { NavbarComponent } from './components/navbar/navbar.component';
import { HomeComponent } from './components/home/home.component';
import { ClubsComponent } from './components/clubs/clubs.component';
import { SearchByCountiesComponent } from './components/search-by-counties/search-by-counties.component';
import { SearchByClubsComponent } from './components/search-by-clubs/search-by-clubs.component';
import { SearchSportsComponent } from './components/search-sports/search-sports.component';
import { SearchClubsComponent } from './components/search-clubs/search-clubs.component';    

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'club-category/search', component: SearchByClubsComponent },
  { path: 'club-category/search/:county_id', component: SearchByClubsComponent },
  { path: 'counties/search', component: SearchByCountiesComponent },
  { path: ':slug/search', component: SearchSportsComponent },
  { path: ':slug/search/:countyID', component: SearchSportsComponent },
  { path: 'clubs/search', component: SearchClubsComponent },
  { path: 'club/:id', component: ClubsComponent }
]

@NgModule({
  exports: [RouterModule],
  imports: [
    RouterModule.forRoot(routes)
  ],
  declarations: []
})
export class AppRoutingModule { }

搜索俱乐部component.ts

import { Component, OnInit } from '@angular/core';
import { Clubs } from '../../models/clubs';
import { DataService } from '../../services/data.service';

@Component({
  selector: 'app-search-clubs',
  templateUrl: './search-clubs.component.html',
  styleUrls: ['./search-clubs.component.scss']
})
export class SearchClubsComponent implements OnInit {
  //Declare Properties
  clubs: Clubs[];

    constructor(
      private dataService: DataService
    ) { }

  ngOnInit() {
    //Get all Clubs
    this.dataService.getClubs().subscribe(clubs => {
      console.log('Response has been received ');
      this.clubs = clubs;            
    });
  }

}

data.service.ts

import { Injectable } from "@angular/core";    
import { Observable } from "rxjs/Observable";    
import { ClubType } from "../models/clubtype";
import { County } from "../models/county";
import { SportCategory } from "../models/SportCategory";
import { Clubs } from "../models/Clubs";    
import { HttpClientModule, HttpClient } from "@angular/common/http";

@Injectable()
export class DataService {
  //Declare properties
  localHost = "http://localhost:3000";

  constructor(private httpClient: HttpClient) {}

  //Get ClubTypes
  getClubTypes(): Observable<ClubType[]> {
    return this.httpClient.get<ClubType[]>(
      this.localHost + "/club-category/search"
    );
  }

  //Get ClubTypes
  getClubTypesByCounty(countyID): Observable<ClubType[]> {
    return this.httpClient.get<ClubType[]>(
      this.localHost + '/club-category/search/'+ countyID
    );
  }

  //Get Counties
  getCounties(): Observable<County[]> {
    return this.httpClient.get<County[]>(this.localHost + "/counties/search");
  }

  //Get Counties
  getSportCategory(slug): Observable<SportCategory[]> {
    return this.httpClient.get<SportCategory[]>(
      this.localHost + '/'+ slug +'/search'
    );
  }

  //Get Specific Category By County
  getSportCategoryByCounty(slug, countyID): Observable<SportCategory[]> {
    return this.httpClient.get<SportCategory[]>(
      this.localHost + '/'+ slug +'/search/' + countyID
    );
  }

  //Get Clubs
  getClubs(): Observable<Clubs[]> {        
    return this.httpClient.get<Clubs[]>(this.localHost + "/clubs/search"); 
  }
}

//服务器端

app.js

const express = require("express");
const path = require('path');
const mysql = require('mysql');
const connectionPool = require('./config/database');

//Create Connection
const db = mysql.createConnection({
  host:'localhost',
  user: 'someUser',
  password: '******',
  database: 'dataBaseName'
});

db.connect((err) =>{
  if(err){
    console.log(err);
    throw err;
  }
  console.log('MySQL connected...');
});

const app = express();

//JSON Prettify
app.set('json spaces', 40);

// Add headers
app.use(function (req, res, next) {

  // Website you wish to allow to connect
  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');

  // Request methods you wish to allow
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

  // Request headers you wish to allow
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

  // Set to true if you need the website to include cookies in the requests sent
  // to the API (e.g. in case you use sessions)
  res.setHeader('Access-Control-Allow-Credentials', true);

  // Pass to next layer of middleware
  next();
});  

//Set Routes
const clubcategories = require('./routes/club-categories');
const counties = require('./routes/counties');
const sportcategories = require('./routes/sport-categories');
const clubs = require('./routes/clubs');


//Use Routes
app.use('/club-category', clubcategories);
app.use('/counties', counties);
app.use('/sport', sportcategories);
app.use('/clubs', clubs);


//Set port
const port = process.env.PORT || 3000;

//Set up server
app.listen(port, () => {
  console.log(`Server started on port ${port}`);
});

clubs.js

const express = require("express");
const router = express.Router();
const connectionPool = require('../config/database');

//Get clubs
router.get("/search", (req, res) => {
  //Get connection from connection pool
  connectionPool.getConnection((err, dbConnection) =>{
    if(err){
      console.log(err);
    } else{
      let sql = 'Select * FROM clubs';

      let query = dbConnection.query(sql, (err, clubs)=> {
        if(err) console.log(err);
        console.log(clubs);
        //res.status(200).send(clubs);
        res.json(clubs);
      });

      //release connection back to pool
      dbConnection.release();
    }
  });
});

module.exports = router;

在服务器端接收请求并执行代码。我看到在发送响应之前在服务器端控制台上记录的俱乐部对象数组。但是,在客户端,响应是未定义的(如我调试时所见)我在客户端登录的“已收到响应”行永远不会输出。

我已经对服务器的其他四个调用采用了相同的方法,并且没有任何问题。在这种情况下,我无法看到我出错的地方。你能帮忙找出问题吗?

3 个答案:

答案 0 :(得分:0)

更新服务方法如下

//Get Clubs
    getClubs(): Observable<Clubs[]> {
       return this.httpClient.get<Clubs[]>(this.localHost + "/clubs/search").map(response => response.json());    
    }

答案 1 :(得分:0)

在你的服务方clubs.js中,你在res.json(俱乐部)之前错过了返回。 这就是为什么它没有返回任何价值。

编辑:或者更好的是使用新的res.status(200).send(俱乐部)。

答案 2 :(得分:0)

我发现了这个问题。它与Http Response无关。我在Chrome中检查了网络,发现浏览器收到了响应。 我使用Augury扩展(For Angular)并且看到路由器实际上路由回SearchSportsComponent而不是SearchClubsComponent。

我重新安排了下面概述的序列并解决了这个问题。我需要进一步理解路由以理解为什么会这样。希望将来会有其他人。

下面提到的代码更改:

APP-routing.module.ts

    const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'club-category/search', component: SearchByClubsComponent },
  { path: 'club-category/search/:county_id', component: SearchByClubsComponent },
  { path: 'counties/search', component: SearchByCountiesComponent },
  { path: 'clubs/search', component: SearchClubsComponent },
  { path: ':slug/search', component: SearchSportsComponent },
  { path: ':slug/search/:countyID', component: SearchSportsComponent },  
  { path: 'club/:id', component: ClubsComponent }
]