无法连接我的node.js服务器到Angular前端客户端



我用node.js和express构建了一个服务器,并将其连接到postgres数据库。使用邮差,我可以看到我的端点正在工作,并正确地从我的数据库中发布/删除/获取项目。

我用Angular创建了一个前端,创建了一个服务。使用getTodos()方法。我相信我添加了一切我需要的方法,我打印的结果。我在我的组件文件中订阅了这个方法,我在控制台中得到了两个不同的响应。

  1. 这一大堆对象包含了我想要的数据加上一堆废话。
{
"command": "SELECT",
"rowCount": 4,
"oid": null,
"rows": [
{
"todo_id": 7,
"description": "travel",
"title": "I need to schedule covid tests",
"date": null
},
{
"todo_id": 8,
"description": "travel",
"title": "I need to schedule covid tests",
"date": null
},
{
"todo_id": 10,
"description": "I need to schedule covid tests",
"title": "travel",
"date": "2022-04-23T05:00:00.000Z"
},
{
"todo_id": 11,
"description": "I need to get this done",
"title": "tech interview",
"date": "2022-04-30T05:00:00.000Z"
}
],
"fields": ...
}
  1. 两个错误都说......错误:NG0900:尝试diff '[object object]'时出错。只允许使用数组和可迭代对象

我会尽量分享我所看到的。由于

这里是试图使用数据

的HTML
<div 
class="card"
*ngFor="let todo of filteredTodos "
[title]="todo.todoTitle"
[style.width.rem]="cardHeightAndWidth"
[style.height.rem]="cardHeightAndWidth"
[style.margin.rem]="cardMargin"
>

服务文件

import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
import { ITodo } from './todo';

@Injectable({
providedIn: 'root',
})
export class TodoService {
private rootUrl: string = 'http://localhost:3000/todos';
constructor(private http: HttpClient) {}
getTodos(): Observable<ITodo[]> {
return this.http.get<ITodo[]>(this.rootUrl).pipe(
tap((data) => {
console.log('All data', JSON.stringify(data));
}),
catchError(this.handleError)
);
}

,这里是它订阅的组件文件

ngOnInit(): void {
this.todoService.getTodos().subscribe({
next: todos => {
this.todos = todos;
this.filteredTodos = todos;
},
error: err => this.errorMessage = err
});
}

这是项目的后端

const express = require("express");
const app = express();
const cors = require('cors');

const pool = require("./db");
app.use(cors());
app.use(express.json());

//routes
//get all todos
app.get("/todos", async (req, res) => {
try {
const todoList = await pool.query("SELECT * FROM todo");
res.json(todoList);
} catch (err) {
console.error(err.message);
}
});
//create a todo
app.post("/todo", async (req, res) => {
try {
const { title, description, date } = req.body;
const newTodo = await pool.query(
"INSERT INTO todo (title, description, date) VALUES ($1, $2, $3) RETURNING *",
[title, description, date]
);
res.json(newTodo.rows);
} catch (err) {
console.error(err.message);
}
});
// update
app.put("/:id", async (req, res) => {
try {
const { id } = req.params; // where
const { description, title } = req.body; // set
const updateTodo = await pool.query(
"UPDATE todo SET description = $1 WHERE todo_id = $2",
[description, id]
);
res.json("updated todo");
} catch (err) {
console.error(err.message);
}
});
//delete
app.delete("/todos/:id", async (req, res) => {
try {
const { id } = req.params;
const deleteTodo = await pool.query("DELETE FROM todo WHERE todo_id = $1", [
id
]);
res.json("todo was deleted");
} catch (error) {
console.error(error.message);
}
});
const PORT = 3000;
app.listen(3000 || PORT, () => {
console.log(`server listening on ${PORT}`);
});

我还尝试更改订阅功能以命中数据。行,得到错误信息Property 'rows' does not exist of type 'ITodo[]

ngOnInit(): void {
this.todoService.getTodos().subscribe(
(data: ITodo[]) => {
this.todos = data.rows; // make sure that data is an array
this.filteredTodos = this.todos;
},
(error: String) => (this.errorMessage)
);
}

这是ITodo[]

export interface ITodo {
todoId: number;
todoTitle: string;
todoDueDate: Date;
todoDescription: string;
todoTags: string[];

}

这里是订阅方法

中的console.log todos
{command: 'SELECT', rowCount: 4, oid: null, rows: Array(4), fields: Array(4), …}
RowCtor: null
command: "SELECT"
fields: Array(4)
0: {name: 'todo_id', tableID: 24580, columnID: 1, dataTypeID: 23, dataTypeSize: 4, …}
1: {name: 'description', tableID: 24580, columnID: 2, dataTypeID: 1043, dataTypeSize: -1, …}
2: {name: 'title', tableID: 24580, columnID: 3, dataTypeID: 1043, dataTypeSize: -1, …}
3: {name: 'date', tableID: 24580, columnID: 5, dataTypeID: 1082, dataTypeSize: 4, …}
length: 4
[[Prototype]]: Array(0)
oid: null
rowAsArray: false
rowCount: 4
rows: Array(4)
0: {todo_id: 7, description: 'travel', title: 'I need to schedule covid tests', date: null}
1: {todo_id: 8, description: 'travel', title: 'I need to schedule covid tests', date: null}
2: {todo_id: 10, description: 'I need to schedule covid tests', title: 'travel', date: '2022-04-23T05:00:00.000Z'}
3: {todo_id: 11, description: 'I need to get this done', title: 'tech interview', date: '2022-04-30T05:00:00.000Z'}
length: 4
[[Prototype]]: Array(0)
_parsers: Array(4)
0: null
1: null
2: null
3: null
length: 4
[[Prototype]]: Array(0)
_types:
binary: {}
text: {}
_types: {arrayParser: {…}, builtins: {…}}
[[Prototype]]: Object
[[Prototype]]: Object

这是来自服务文件的所有数据

All data `{"command":"SELECT","rowCount":4,"oid":null,"rows":[{"todo_id":7,"description":"travel","title":"I need to schedule covid tests","date":null},{"todo_id":8,"description":"travel","title":"I need to schedule covid tests","date":null},{"todo_id":10,"description":"I need to schedule covid tests","title":"travel","date":"2022-04-23T05:00:00.000Z"},{"todo_id":11,"description":"I need to get this done","title":"tech interview","date":"2022-04-30T05:00:00.000Z"}],"fields":[{"name":"todo_id","tableID":24580,"columnID":1,"dataTypeID":23,"dataTypeSize":4,"dataTypeModifier":-1,"format":"text"},{"name":"description","tableID":24580,"columnID":2,"dataTypeID":1043,"dataTypeSize":-1,"dataTypeModifier":259,"format":"text"},{"name":"title","tableID":24580,"columnID":3,"dataTypeID":1043,"dataTypeSize":-1,"dataTypeModifier":54,"format":"text"},{"name":"date","tableID":24580,"columnID":5,"dataTypeID":1082,"dataTypeSize":4,"dataTypeModifier":-1,"format":"text"}],"_parsers":[null,null,null,null],"_types":{"_types":{"arrayParser":{},"builtins":{"BOOL":16,"BYTEA":17,"CHAR":18,"INT8":20,"INT2":21,"INT4":23,"REGPROC":24,"TEXT":25,"OID":26,"TID":27,"XID":28,"CID":29,"JSON":114,"XML":142,"PG_NODE_TREE":194,"SMGR":210,"PATH":602,"POLYGON":604,"CIDR":650,"FLOAT4":700,"FLOAT8":701,"ABSTIME":702,"RELTIME":703,"TINTERVAL":704,"CIRCLE":718,"MACADDR8":774,"MONEY":790,"MACADDR":829,"INET":869,"ACLITEM":1033,"BPCHAR":1042,"VARCHAR":1043,"DATE":1082,"TIME":1083,"TIMESTAMP":1114,"TIMESTAMPTZ":1184,"INTERVAL":1186,"TIMETZ":1266,"BIT":1560,"VARBIT":1562,"NUMERIC":1700,"REFCURSOR":1790,"REGPROCEDURE":2202,"REGOPER":2203,"REGOPERATOR":2204,"REGCLASS":2205,"REGTYPE":2206,"UUID":2950,"TXID_SNAPSHOT":2970,"PG_LSN":3220,"PG_NDISTINCT":3361,"PG_DEPENDENCIES":3402,"TSVECTOR":3614,"TSQUERY":3615,"GTSVECTOR":3642,"REGCONFIG":3734,"REGDICTIONARY":3769,"JSONB":3802,"REGNAMESPACE":4089,"REGROLE":4096}},"text":{},"binary":{}},"RowCtor":null,"rowAsArray":false}`

您可以试试这个代码吗:

this.todoService.getTodos().subscribe(
(data: todos) => {
this.todos = data; // make sure that data is an array
this.filteredTodos = todos;
},
(error: err) => this.errorMessage = err
);

最新更新