Ошибка браузера Chrome при выполнении нескольких AJAX-запросов в приложении Python-Flask

#javascript #ajax #google-chrome #flask #cross-browser

#javascript #ajax #google-chrome #flask #кросс-браузер

Вопрос:

В настоящее время я использую команду «python3 -m flask run -h localhost -p 8081» для запуска сервера flask на localhost: 8081. Пользователь может нажимать кнопки для запуска событий; кроме того, обновления данных динамически передаются в графические графики, запускаемые с интервала javascript.

Проблема возникает в Google-Chrome, когда оба асинхронных AJAX-запроса выполняются одновременно ->

На странице есть элементы управления (например, кнопка «Пуск»), которые обрабатывают другие действия. При запуске Mozilla Firefox оба этих запроса будут выполняться без проблем. Однако при использовании Google Chrome запрос на нажатие кнопки начнет зависать через несколько секунд, и для достижения функции «req.done» требуется больше времени, пока в конечном итоге не произойдет сбой страницы. В приведенном ниже коде я написал несколько журналов консоли, которые показывают в консоли браузера, что событие нажатия кнопки перестает отвечать «randomstring» из маршрута python через несколько секунд после запуска. Похоже, это проблема, специфичная для Chrome, поскольку она работает стабильно в firefox.

Пожалуйста, посоветуйте — как я могу изменить это, чтобы надежно работать в обоих браузерах?

код

вот AJAX-запросы javascript-jquery:

 var numerical_count_rate = document.getElementById("totalCounts");
var numerical_error_rate = document.getElementById("errorRate");
var start_btn = document.getElementById("startButtonClick");

var start_btn_clicked = function (){
    console.log("button clicked...")
    req = $.ajax({
        url : "/_start_button_clicked",
        type : "POST",
    });
    console.log("button got this far...")
    req.done(function(data){
        console.log("button got even further !!")
        var data_test = JSON.parse(data)
        var update = data_test.random_string
        console.log(update)
    });
};

var updateInterval = setInterval(update_values, 1000);
    var counts = 0;
    console.log("update_interval fired..")
    function update_values(){
        req = $.ajax({
            url : "/_extend_plot",
            type : "POST",
        });
        req.done(function(data){
            var updates = JSON.parse(data);
            var count_rate_update = {x: [[updates.x_count_rate]],y: [[updates.y_count_rate]]};
            var error_rate_update = {x: [[updates.x_error_rate]],y: [[updates.y_error_rate]]};
            Plotly.extendTraces('plotly_countrate',count_rate_update, [0], 50);
            Plotly.extendTraces('plotly_errorrate',error_rate_update, [0], 50);
            numerical_count_rate.innerHTML = "Total Count Rate: "   updates.y_count_rate.toString().replace(/(d)(?=(d{3}) (?!d))/g, '$1,');
            numerical_error_rate.innerHTML = "Error Rate: "   parseFloat(updates.y_error_rate).toFixed(3).toString()   "%";
        });
        window.onresize = function() {
            Plotly.Plots.resize( 'plotly_countrate' );
            Plotly.Plots.resize( 'plotly_errorrate' )
            };
        counts  ;
        console.log(counts)
    }
  

Вот фрагменты из основного потока -> маршруты Flask, на которые ссылаются запросы ajax в основном app.py файл:

 from flask import Flask, render_template,  request
import queue
import threading
import plotly
import json
import pandas as pd
import numpy as np
import random
import datetime


app = Flask(__name__)


@app.route("/", methods=['GET'])
def index():
    initial_graphs_json = create_plots()
    return render_template("index.html", count_rate_plot=initial_graphs_json[0], error_rate_plot=initial_graphs_json[1])


@app.route("/_extend_plot", methods=['GET', 'POST'])
def push_update():
    timestamp = get_datetime()

    updated_data = queue_q.get()
    with queue_q.mutex:
        queue_q.queue.clear()
    client_post_updates = dict(
        x_count_rate=timestamp,
        x_error_rate=timestamp,
        y_count_rate=updated_data["val0"]   updated_data["val1"],
        y_error_rate=updated_data["val2"])

    updatesJSON = json.dumps(client_post_updates, cls=plotly.utils.PlotlyJSONEncoder)
    return updatesJSON


@app.route("/_start_button_clicked", methods=['GET', 'POST'])
def startstop_clicked():
    update_dict = dict(
        random_string="randomstring"
    )
    print("Python click method triggered...")
    update = json.dumps(update_dict)
    return update


if __name__ == "__main__":
    app.run(host="0.0.0.0", port="8081", debug=True)
  

запуск — python версии 3.7, jquery версии 3.5.1

Ответ №1:

Обновление: РЕШЕНО

Проблема решена путем преобразования функций в асинхронные вызовы и изменения короткого опроса на длительный. Похоже, что Chrome имеет встроенную функциональность, позволяющую оставлять запросы в «состоянии ожидания», а короткий интервал опроса заполнял очередь браузера новыми запросами, что приводило к остановке. Все еще не совсем понятно, почему этого не происходит в firefox, но длительный опрос, основанный на одном таймере под управлением мьютекса и общей памяти между потоками на стороне сервера, является гораздо лучшей общей практикой. Таким образом, частота принудительных обновлений контролируется только доступностью данных, а не опросом по таймеру.

Новый JS-код:

 var start_btn_clicked = async function (){
    req = $.ajax({
        url : "/_start_button_clicked",
        type : "POST",
    });
    req.done(async function(data){
        var data_test = JSON.parse(data);
        var update = data_test.random_string;
    });
};

update_values();
async function update_values(){
    req = $.ajax({
        url : "/_extend_plot",
        type : "POST",
        async: true,
        cache: false,
        timeout: 30000,
        success: async function(data){
            console.log(req);
            var updates = JSON.parse(data);
            var count_rate_update = {x: [[updates.x_count_rate]],y: [[updates.y_count_rate]]};
            var error_rate_update = {x: [[updates.x_error_rate]],y: [[updates.y_error_rate]]};
            Plotly.extendTraces('plotly_countrate',count_rate_update, [0], 50);
            Plotly.extendTraces('plotly_errorrate',error_rate_update, [0], 50);
            numerical_count_rate.innerHTML = "Total Count Rate: "   updates.y_count_rate.toString().replace(/(d)(?=(d{3}) (?!d))/g, '$1,');
            numerical_error_rate.innerHTML = "Error Rate: "   parseFloat(updates.y_error_rate).toFixed(3).toString()   "%";
            setTimeout(update_values, 1000);
        },
    });
    window.onresize = async function() {
        Plotly.Plots.resize( 'plotly_countrate' );
        Plotly.Plots.resize( 'plotly_errorrate' );
        };
}