javascript - HTML标记阻止 ajax POST
问题描述
我正在使用 Flask 将视频流式传输到网页。
- 视频流自行工作。
- 然后,我添加了一个与 python 后端函数接口并获取要显示的数据的模式。
- 模态显示从 python 函数返回的数据。
- 一旦我第一次激活
<img>
流式传输视频和模态的 html 标签,视频流会阻止 ajax POST,因此模态无法显示数据。
条件 4) 失败。似乎<img>
标签阻止了 ajax POST。
此代码是我几天前提交并回答的先前帖子的延续 https://stackoverflow.com/questions/57067923/returned-python-values-break-html-table-after-inserting-in-javascript-array
这是重现我的错误的完整代码,在此先感谢。
# project/get_data.py: python backend module that return data to be displayed in a modal table
class GetData:
def __init__(self):
pass
def records(self):
return [(1, 'John Smith', 'Canada'),
(2, 'Jane Doe', 'United States'),
(3, 'John Doe', 'Mexico')]
# project/camera.py : camera module that returns encoded frames
import cv2
class VideoCamera(object):
def __init__(self):
self.video = cv2.VideoCapture(0)
def __del__(self):
self.video.release()
def get_frame(self):
ret, frame = self.video.read()
if ret:
ret, jpeg = cv2.imencode('.jpg', frame)
return jpeg.tobytes()
<!-- project/templates/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
body {font-family: Arial, Helvetica, sans-serif;}
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content */
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
}
/* The Close Button */
.close {
color: #aaaaaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
</style>
</head>
<body>
<!-- Trigger/Open The Modal -->
<button id="myBtn">Open Modal</button>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<div id="dvTable"></div>
</div>
</div>
<style>
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
</style>
<br><br>
<!--video feed, uncomment the <img> tag to reproduce error===-->
<!--<img id="vid" src="{{ url_for('video_feed') }}">-->
<!--video feed ==============================================-->
<script src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
crossorigin="anonymous">
</script>
<script>
// Get the modal
var modal = document.getElementById("myModal");
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks the button, open the modal
btn.onclick = function() {
modal.style.display = "block";
//var Table = document.getElementById("dvTable").innerHTML = "";
$("#dvTable tr").remove();
$.ajax({
url: "/_get_data/",
type: "POST",
success: function(resp){
$('div#dvTable').append(resp.data);
}
});
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
</script>
</body>
</html>
<!--project/templates/response.html-->
<table>
<tr>
<th>Customer Id</th>
<th>Name</th>
<th>Country</th>
</tr>
{% for elem in myList %}
<tr>
<td>{{elem[0]}}</td>
<td>{{elem[1]}}</td>
<td>{{elem[2]}}</td>
</tr>
{% endfor %}
</table>
# project/app.py : flask framework
from flask import Flask, render_template, Response, jsonify
from camera import VideoCamera
from get_data import GetData
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/_get_data/', methods=['POST'])
def _get_data():
data = GetData()
myList = data.records()
return jsonify({'data': render_template('response.html', myList=myList)})
def gen(camera):
"""Video streaming generator function."""
while True:
frame = camera.get_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
@app.route('/video_feed')
def video_feed():
"""Video streaming route. Put this in the src attribute of an img tag."""
return Response(gen(VideoCamera()),
mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == "__main__":
app.run(debug=True)
如何重现错误
- 中的
<img>
标签templates/index.html
目前已被注释掉:
<!--video feed, uncomment the <img> tag to reproduce error===-->
<!--<img id="vid" src="{{ url_for('video_feed') }}">-->
<!--video feed ==============================================-->
- 跑
python app.py
- 在浏览器中打开 localhost:5000 并点击,
open modal
应该可以看到get_data.py
返回的客户信息处于工作状态。 - 停止烧瓶服务器
Ctrl+C
。取消注释<img>
标签templates/index.html
并将相机连接到您的 PC 并python app.py
第二次运行。点击open modal
,获取数据创建模态表失败。
预期结果是在视频流式传输时显示模态内容。目前,显示结果的唯一方法<img>
是禁用标签,谢谢。
解决方案
我找到了解决这个问题的方法:1)更新到 1.1.1 的烧瓶修复了这个问题,没有对代码做任何更改。
2)另一种解决方案是放弃ajax请求并template.html
进行以下更改:
<!-- project/templates/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
body {font-family: Arial, Helvetica, sans-serif;}
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content */
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
}
/* The Close Button */
.close {
color: #aaaaaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
</style>
</head>
<body>
<!-- OPEN THE CONTENT WHEN USER CLICKS MODAL-->
<button id="myBtn" onclick="document.getElementById('myModal').style.display='block'">Open Modal</button>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<div id="dvTable">
<!-- INSERT THE TABLE IN THE MODAL-->
<table>
<table>
<tr>
<th>Customer Id</th>
<th>Name</th>
<th>Country</th>
</tr>
<tr>
<!-- loop through data -->
{% for elem in myList %}
<tr>
<td>{{elem[0]}}</td>
<td>{{elem[1]}}</td>
<td>{{elem[2]}}</td>
</tr>
{%endfor %}
</tr>
</table>
</table>
</div>
</div>
</div>
<style>
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
<br><br>
</style>
<img id="bg" src="{{ url_for('video_feed') }}">
<!--<script src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
crossorigin="anonymous">
</script>-->
<script>
// Get the modal
var modal = document.getElementById("myModal");
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
//AJAX POST COMMENTED OUT
/*
// When the user clicks the button, open the modal
btn.onclick = function() {
modal.style.display = "block";
//var Table = document.getElementById("dvTable").innerHTML = "";
$("#dvTable tr").remove();
$.ajax({
url: "/_get_data/",
type: "POST",
success: function(resp){
$('div#dvTable').append(resp.data);
}
});
}
*/
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
</script>
</body>
</html>
# project/app.py
from flask import Flask, render_template, Response, jsonify
from camera import VideoCamera
from get_data import GetData
app = Flask(__name__)
@app.route('/')
def index():
# get the data and render it to the index page with a variable
data = GetData()
myList = data.records()
return render_template('index.html', myList=myList)
""" NO LONGER NEEDED TO SERVE DATA TO AJAX POST
@app.route('/_get_data/', methods=['POST'])
def _get_data():
data = GetData()
myList = data.records()
return jsonify({'data': render_template('response.html', myList=myList)})
"""
def gen(camera):
"""Video streaming generator function."""
while True:
frame = camera.get_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
@app.route('/video_feed')
def video_feed():
"""Video streaming route. Put this in the src attribute of an img tag."""
return Response(gen(VideoCamera()),
mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == "__main__":
app.run(debug=True)
希望这对其他人有帮助。
推荐阅读
- sql - 将 T-SQL 命令转换为 lambda 表达式
- rxjs - 如何在 RxJs 中获得可观察的按钮状态?
- ios - 如何在 iOS 中与 CAShapeLayers 相交
- javascript - Javascript中是否有“afterChange”事件而不是“change”?
- oop - 如何以最简单的方式在 Forth 中实现具有非唯一方法名的类?
- java - “int variable = 0;”有什么区别?和“int变量;变量= 0;” 在 Java 类中?
- python - 在保持元素和列表长度的列表中查找每个可能的元素配置
- c# - 如何在 WPF 中使用 MultiBinding
- ubuntu - Ubuntu 18 VS Code 错误 Enoent:没有这样的目录,lstat'/snap/code'
- python - mininet 和 scapy 中的多线程或多处理