页面刷新后,Ajax POST to Flask无法正常工作

时间:2018-11-07 18:18:51

标签: javascript python jquery ajax flask

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

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

相关代码段在这里:

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,但flask似乎无法接收到它。请求超时。

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

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

为什么会这样?显然,该代码可以实现其主要目的,但是页面刷新在某种程度上破坏了某些事情。

2 个答案:

答案 0 :(得分: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方法,并使用帖子进行移动。

答案 1 :(得分:0)

感谢@Peter van der Wal向我指出解决方案。

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

解决方案是在 on 上使用 threaded 选项启动应用程序:

之前:

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

现在:

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

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