Flask/Typescript前后端集成问题:POST请求无法触发
Flask/TypeScript前后端集成POST请求失败排查
我在做Flask/Typescript服务端与客户端集成开发时,遇到POST请求无法正常工作的问题:点击按钮后,程序本该完成录音并将录音文件发送至服务器,服务器处理后返回接收响应,但实际POST请求根本没发起。
Flask服务端代码(app.py)
from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/api/receive-recording', methods=['GET', 'POST']) # Allow both GET and POST def receive_recording(): if request.method == 'POST': try: audio_data = request.data # Process the audio_data as needed return jsonify(message='I got the recording') except Exception as e: return jsonify(error=str(e)), 400 else: return jsonify(message='Hello! This is the audio recording endpoint.') if __name__ == '__main__': app.run(debug=True)
TypeScript前端代码(App.tsx)
import React, { useState, useRef } from 'react'; function App() { const [recording, setRecording] = useState<Blob | null>(null); const [serverResponse, setServerResponse] = useState<string>(''); const mediaRecorder = useRef<MediaRecorder | null>(null); const chunks: Blob[] = []; const startRecording = () => { navigator.mediaDevices.getUserMedia({ audio: true }) .then((stream) => { mediaRecorder.current = new MediaRecorder(stream); mediaRecorder.current.ondataavailable = (event) => { if (event.data.size > 0) { chunks.push(event.data); } }; mediaRecorder.current.onstop = () => { const recordedBlob = new Blob(chunks, { type: 'audio/wav' }); setRecording(recordedBlob); chunks.length = 0; // Reset chunks }; mediaRecorder.current.start(); }) .catch((error) => console.error('Error starting recording:', error)); }; const stopRecording = () => { if (mediaRecorder.current) { mediaRecorder.current.stop(); if (recording) { sendRecording(); } } }; const sendRecording = async () => { try { const response = await fetch('/api/receive-recording', { method: 'POST', body: recording, }); const data = await response.json(); setServerResponse(data.message); } catch (error) { console.error('Error sending recording:', error); } }; return ( <div className="App"> <h1>Audio Recording and Communication</h1> {!recording ? ( <button onClick={startRecording}>Start Recording</button> ) : ( <> <button onClick={stopRecording}>Stop Recording and Send</button> <audio controls src={URL.createObjectURL(recording)} /> {serverResponse && <p>Server Response: {serverResponse}</p>} </> )} </div> ); } export default App;
问题原因及修复方案
核心问题:状态更新异步导致sendRecording未被调用
setRecording是React异步状态更新操作,调用mediaRecorder.current.stop()后,onstop回调里执行setRecording(recordedBlob),但此时stopRecording函数里紧接着判断if (recording),这时recording还没更新为新生成的Blob值,所以sendRecording根本没触发。
修复方案(二选一即可)
方案1:将发送逻辑移到onstop回调中
直接在生成录音Blob后调用发送函数,避免依赖异步更新的状态:
// 修改onstop回调 mediaRecorder.current.onstop = () => { const recordedBlob = new Blob(chunks, { type: 'audio/wav' }); setRecording(recordedBlob); chunks.length = 0; sendRecording(recordedBlob); // 直接传入Blob }; // 修改sendRecording函数 const sendRecording = async (audioBlob: Blob) => { try { const response = await fetch('/api/receive-recording', { method: 'POST', body: audioBlob, }); const data = await response.json(); setServerResponse(data.message); } catch (error) { console.error('Error sending recording:', error); } }; // 修改stopRecording函数,移除里面的sendRecording调用 const stopRecording = () => { if (mediaRecorder.current) { mediaRecorder.current.stop(); } };
方案2:用useEffect监听状态变化
通过监听recording状态,当它从null变为Blob时自动触发发送:
// 导入useEffect import React, { useState, useRef, useEffect } from 'react'; // ... 其他代码 ... // 添加useEffect监听 useEffect(() => { if (recording) { sendRecording(); } }, [recording]); // 修改stopRecording函数,移除里面的sendRecording调用 const stopRecording = () => { if (mediaRecorder.current) { mediaRecorder.current.stop(); } };
额外注意事项
- 跨域问题:如果前端(比如React默认3000端口)和后端(Flask默认5000端口)不在同一端口,需要给Flask添加CORS支持:安装
flask-cors,然后在代码中添加:
from flask_cors import CORS CORS(app)
- 请求URL正确性:跨域场景下,
fetch的URL要写完整地址,比如http://localhost:5000/api/receive-recording
内容的提问来源于stack exchange,提问作者Ariel Makovoz
相关产品推荐
相关产品推荐

