【问题标题】:Ajax POST to Flask not working after page refresh页面刷新后,Ajax POST 到 Flask 不起作用
【发布时间】:2018-11-07 18:18:50
【问题描述】:

我正在改进远程控制望远镜的系统。 Raspberry Pi 运行烧瓶,并为连接到望远镜的相机提供视频流。望远镜的调焦器由 Arduino 控制的步进电机驱动。服务器提供一个显示视频流的网站,并提供两个按钮来移动调焦器。

当点击任一按钮时,客户端会向 RasPi 发送 POST,然后 RasPi 会告诉 Arduino 移动焦点。但至关重要的是,我不希望页面在重新聚焦时刷新。因此,我使用 jQuery 和 Ajax 来抑制页面刷新。

相关代码sn-ps在这里:

Python/Flask 代码:

@app.route('/stream/<wcam>', methods=['GET'])
def stream_get(wcam):
    class FocuserForm(FlaskForm):
        nsteps = IntegerField('# steps: ', default=1)
        focuser_in = SubmitField('Focuser in')
        focuser_out = SubmitField('Focuser out')

    form = FocuserForm()
    return render_template('stream.html', wcam=wcam, form=form)

@app.route('/stream/<wcam>', methods=['POST'])
def stream_post(wcam):
    results = request.form
    arduino_serial = SerialFocuser()
    if results['caller'] == "focuser_in":
        command = "MVD" + results['steps'] + "\n"
        arduino_serial.send_command(command)
    elif results['caller'] == "focuser_out":
        command = "MVU" + results['steps'] + "\n"
        arduino_serial.send_command(command)
    return ''

网页(stream.html):

<html>
    <head>
        <title>Video Streaming</title>
        <style>
            ...
        </style>

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

        <script>
                $(document).ready(function() {});
        </script>
      </head>

    <body>
        <h1>Streaming camera {{ wcam }}</h1>
        <br>
        <img id="bg" src="{{ url_for('video_feed', wcam=wcam) }}", height="480" width="640">
        <a href="{{ url_for('index') }}">Back</a>
        <br>


    <!--######################################################-->
    <!--#  Focuser handling -->
    <!--######################################################-->

    <br>
    <form id="flaskform" method="POST">
        <p>
        {{ form.nsteps.label }} {{ form.nsteps() }} &nbsp;
        {{ form.focuser_in() }} &nbsp;
        {{ form.focuser_out() }}
        </p>
    </form>

    <script>
    // $(document).ready(function() { // Moved to header

            var form = document.getElementById('flaskform');
            function onSubmit(event) {
                console.log('onSubmit function');
                var objectID = event.explicitOriginalTarget.id;
                var nsteps = form.nsteps.value;
                var return_data = {caller: "", steps: nsteps};
                if (objectID == "focuser_in") {
                    return_data.caller = objectID;
                    console.log("Focuser_in detected");
                } else if (objectID == "focuser_out") {
                    return_data.caller = objectID;
                    console.log("Focuser_out detected");
                } else if (objectID == "nsteps") {
                    console.log("nsteps detected");
                    event.preventDefault();
                    return;
                } else {
                    console.log("No matches");
                    return;
                }
                console.log("About to run Ajax");
                $.ajax({
                    url: "stream.html",
                    type: "post",
                    data: return_data,
                    success: function(response) {
                        console.log('It worked!');
                    },
                    error: function(xhr, status, text) {
                        console.log('An error occurred:', status,"; ", text);

                    },
                    timeout: 1000 // 1s
                }); // Ajax
                console.log("After running Ajax");
                if (event) { event.preventDefault(); }

            }
            // prevent when a submit button is clicked
            form.addEventListener('submit', onSubmit, false);

            //<!--form.addEventListener('submit', onSubmit, false);-->
            // prevent submit() calls by overwriting the method
            form.submit = onSubmit;

    //});  // Moved to header
    </script>
    </body>
</html>

问题如下:

如果我在客户端浏览器上刷新页面然后单击一个按钮,ajax 会 POST,但烧瓶似乎没有收到它。请求超时。

如果我现在重新启动服务器(我正在使用 PyCharm 开发它,所以我只需单击重新运行)而不刷新客户端中的页面,然后单击一个按钮,flask 确实获得 POST,并且焦点工作就像一个魅力。

如果我再次刷新页面,那么按钮将停止工作,直到我重置服务器。

为什么会这样?显然,代码的主要用途是有效的,但页面刷新却以某种方式破坏了某些东西。

【问题讨论】:

  • 网址:“stream.html”?你应该把 URL 放在这里而不是 html。

标签: javascript python jquery ajax flask


【解决方案1】:

我曾经遇到过类似的问题,摄像头线程阻塞了所有调用。当您重置服务器时,您的相机源是否仍然运行(在单击按钮之前)? 因为基本上你调用了你的相机提要两次——第一次是刷新页面时的 get 调用,然后是 post 调用。

为了清晰起见,我建议您将提交的代码重构为替代函数:

@app.route('/stream/<wcam>', methods=['POST'])
def moveCommand:
       if form.is_submitted():
    # POST method
    results = request.form
    arduino_serial = SerialFocuser()
    if results['caller'] == "focuser_in":
        command = "MVD" + results['steps'] + "\n"
        arduino_serial.send_command(command)
    elif results['caller'] == "focuser_out":
        command = "MVU" + results['steps'] + "\n"
        arduino_serial.send_command(command)

所以基本上你只保留你的 get 方法用于流式传输,并使用 post 来移动。

【讨论】:

  • 嗨,彼得。这是阻止服务器的视频源。我也采纳了你关于拆分方法的建议,虽然它本身并没有解决问题,只会让代码更优雅。我将发布我找到的解决方案以供其他人将来参考。你没有给我解决方案,但你已经指出了我的方向,所以你值得称赞。我希望这次声望的提升可以帮助你尽快在这里制作 cmets。非常感谢!
【解决方案2】:

感谢@Peter van der Wal 为我指明了解决方案。

视频流媒体有一个while True 循环,它不断地从摄像头获取帧,从而锁定线程。

解决方案是使用 threading 选项启动应用程序on

之前:

app.run(host='0.0.0.0', debug=True)

现在:

app.run(host='0.0.0.0', debug=True, threaded=True)

这允许视频流线程自行继续,同时允许服务器处理其他命令。

【讨论】:

    猜你喜欢
    • 2016-10-04
    • 2016-08-15
    • 2014-08-23
    • 2020-02-15
    • 1970-01-01
    • 2018-06-14
    • 1970-01-01
    • 2019-02-24
    • 1970-01-01
    相关资源
    最近更新 更多