我正在处理一个特定的 Post 调用,该调用传递一个数组,该数组不想与我创建的用于进行 MySQL 查询的 Express Node.js 服务器通信。这是启动整个事情的方法代码:
questionsSubmit(){
console.log('Questions Submited')
// Initialize an array to store the answers
const answers: {participantId: number, optionId: number, scorePoints: number}[] = [];
// Iterate over the form controls
Object.keys(this.questionsForm.controls).forEach(key => {
const control = this.questionsForm.controls[key]
// Check if the control is a FormGroup and contains 'value' property
if (control instanceof FormControl && control.value) {
const participantId = this.participantId
const [optionId, scorePoints] = control.value.split('-').map(Number)
// Create an Answer object and push it to the answers array
answers.push({
participantId,
optionId,
scorePoints
})
}
})
if(!this.participantId){
this.showAlert = true
this.step = 0
console.log('Please complete and submit the Participant\'s profile before submitting to the Needs questionnaire' )
return
}
if(this.questionsForm.valid){
this.masterService.saveAnswers(answers)
}
// console.log(answers);
}
此 Component.ts 代码可以很好地收集所有必要的 FormControl 并组装对象数组。我已经验证了数百万次,这始终是 console.log 的结果 然后它调用 Service.ts 方法将数组发布到服务器。方法如下:
saveAnswers(answers: {participantId: number, optionId: number, scorePoints: number}[]){
return this.http.post<{participantId: number, optionId: number, scorePoints: number}[]>(`http://localhost:3000/hello`, answers, this.httpOptions)
.pipe(catchError(this.errorHandlerService.handleError<any>("post")));
}
但这就是所有通信都消失的地方。浏览器控制台中没有错误,后端终端中也没有错误。我在每个地方都放了一百万个console.logs,但什么也没有,Nada!疯狂的是我有 GET、PUT、DELETE 和其他 POST,而且它们都工作正常。服务器 POST 到数据库也工作得很好。我使用 Postman 推送相同的数据并且有效。
我的服务器由6个文件组成(用于启动服务器的中间件的Index.js,1个路由文件,用于处理请求和响应的控制器,以及用于查询数据库的模型文件,最后2个仅用于处理与数据库的连接)
索引.js
const express = require('express')
const bodyParser = require('body-parser');
const app = express()
const ports = process.env.PORT || 3000
const participantRoutes = require('./routes/participant-routes')
const questionRoutes = require('./routes/question-routes')
const errorController = require('./controllers/error')
// Middleware to parse JSON bodies
app.use(express.json())
// app.use(bodyParser.json())
app.use((req, res, next) => {
console.log(`Incoming request: ${req.method} ${req.url}`);
next();
});
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization')
next()
})
// Routes
app.use('/participants', participantRoutes);
app.use('/hello', questionRoutes);
// http://localhost:3000/questions-options-answers
app.use(errorController.get404)
app.use(errorController.get500)
app.listen(ports, () => console.log(`Hello_Kitty (Server): listening on port ${ports}`))
路由器.js
const express = require('express')
const controller = require('../controllers/controller')
const router = express.Router()
// Question Routes
router.get('/', controller.getAllQuestionsWithOptions);
router.post('/', controller.postAnswersFromOptions);
console.log('Hello From Routes')
module.exports = router
控制器.js
const Question = require('../models/question-model')
exports.getAllQuestionsWithOptions = async (req, res, next) => {
try {
const questionsWithOptions = await Question.fetchAllQuestions()
res.status(200).json(questionsWithOptions)
} catch (error) {
console.error('Error fetching questions with options:', error)
res.status(500).json({ error: 'Internal server error' })
}
}
exports.postAnswersFromOptions = async (req, res, next) => {
try {
console.log('From postAnswersFromOptions')
console.log(req.body)
const postAnswersWithOptions = await Question.postsAnswers(req.body)
res.status(200).json(postAnswersWithOptions)
} catch (error) {
console.error('Error fetching questions with options:', error)
res.status(500).json({ error: 'Internal server error' })
}
}
模型.js
const db = require('../util/database')
const Query = require('./query-builder')
const mysql = require('mysql');
module.exports = class Question {
constructor(question, options) {
this.question = question;
this.options = options;
}
static async fetchAllQuestions() {
try {
// Fetch questions from the database
const [questions] = await db.execute('SELECT * FROM Questions');
// Fetch options for each question
const questionsWithOptions = [];
for (const question of questions) {
const [options] = await db.execute('SELECT * FROM Options WHERE questionId = ?', [question.questionId]);
const formattedOptions = options.map(option => ({ id: option.optionId, option: option.questionOption,
points: option.points}));
questionsWithOptions.push({ question: question.question, options: formattedOptions });
}
return { questions: questionsWithOptions };
} catch (error) {
console.error('Error fetching questions with options:', error);
throw error
}
}
static async postsAnswers(answers){
try {
const columns = Object.keys(answers[0]);
const values = answers.map(obj => `(${columns.map(col => mysql.escape(obj[col])).join(', ')})`).join(', ');
const query = `INSERT INTO Answers (${columns.join(', ')}) VALUES ${values}`;
console.log('Query for post answers')
console.log(query)
console.log(values)
return await db.execute(query, [...Object.values(values)])
} catch (error) {
console.error(error)
throw error
}
}
}
如果我将 Postman 与我之前展示的相同数组一起使用,服务器调用工作得很好,数据库也工作得很好,问题是它不想与我的 Angular 应用程序一起工作。除了我提到的那个以外,Express 服务器与其他调用都可以正常工作,最大的问题是我没有从任何地方收到错误。不是来自浏览器控制台,不是来自终端等。请您告诉我我缺少什么或为我指出正确的方向吗?我一直大量使用 ChatGPT,因此我进行了一些广泛的故障排除。我知道问题可能很小,就像经常发生的那样,但我恳求你们提供帮助。
当您调用
saveAnswers
时,它会返回 Observable<...>
。
Observables 仅在订阅时执行(请参阅 https://angular.io/guide/observables#subscribing)。
当您在第一个代码片段中调用
this.masterService.saveAnswers(answers)
时,它实际上是在调用 saveAnswers 方法,但实际上没有传输任何数据,因为 this.http.post()
在执行任何工作之前正在等待侦听器。
您的前端代码是正确的,不会引发任何错误,因为您可以执行以下操作:
let answersObservable: Observable<any>;
if (this.questionsForm.valid) {
answersObservable = this.masterService.saveAnswers(answers)
} else {
answersObservable = this.masterService.countWrongAnswers(answers)
}
answersObservable.subscribe({
next: _ => {
/* Only do the following when we received a response from the server, can be either saveAnswers or countWrongAnswers */
}
})
在您的代码片段中,您可以交换以下代码:
if(this.questionsForm.valid){
this.masterService.saveAnswers(answers)
}
如果你不关心服务器响应,就用这个:
if(this.questionsForm.valid){
this.masterService.saveAnswers(answers).subscribe(_=>{})
}
或者如果您想处理响应:
if(this.questionsForm.valid){
this.masterService.saveAnswers(answers).subscribe({
next: result => {
displayResult(result)
},
error: error => {
showError(error)
}
})
}