Reputation: 1
I am currently using command "python3 -m flask run -h localhost -p 8081" to run a flask server on localhost:8081. The user is able to click buttons to trigger events; additionally, data updates are dynamically pushed to plotly graphs triggered from a javascript interval.
Issue occurs on google-Chrome when both asynchronous AJAX requests are running at the same time-->
There are controls on the page (such as a start button) that handle other actions. When running mozilla firefox, both of these requests will execute with no problems. However, when using google Chrome, the button click request will start to hang after a few seconds, taking longer to reach the "req.done" function until eventually crashing the page. In the code below, I have written some console logs that show in the browser console that the button click event stops replying with "randomstring" from the python route a few seconds after running. This seems to be an issue specific to chrome, as this works consistently on firefox.
Please advise - how could I change this to work across both browsers reliably?
CODE
here are the javascript-jquery AJAX requests:
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)
}
Here are snippets from the main thread --> the Flask routes that the ajax requests reference in the main app.py file:
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)
running- python version 3.7, jquery version 3.5.1
Upvotes: 0
Views: 431
Reputation: 1
Update: SOLVED
Issue solved by converting functions to asynchronous calls and changing short to long polling. It seems chrome has built in functionality to leave requests in "pending state", and the short polling interval was filling up browser queue with new requests, which caused stalling. Still not completely clear why this does not happen on firefox, but long polling based on a single timer under control of mutex and common memory between threads on the server side is much better overall practice. This way, the frequency of pushed updates is controlled only by data being available, rather then being polled on a timer.
New JS code:
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' );
};
}
Upvotes: 0