前提・実現したいこと
Python(flask)でブラウザでボタンを押したらサーバー側で処理を行い、結果をSSEでブラウザ側に表示するサイトを作っています。しかし、ブラウザで表示されるログは、一部が欠落してスキップしてデータが表示されてしまい苦戦しております。(例:①〜⑩の処理を表示したいが、②の処理がブラウザ側では取得することができないことがときどき起こる)
処理内容
ajaxでブラウザ側のボタンを押したらサーバー側で処理の結果をQueueモージュールにてデータを逐次入れていき、それをwhileの中でデータを取り出し、event-streamでブラウザ側に結果を表示しようと試みてますが、思ったように動作することができておりません。(サーバーの処理後ブラウザへ値を渡したいです)
エラー画面・取得できない例
サーバー側のログを見てみると、①〜⑩の処理は取得できているのですが、ブラウザ側では②を取得することができてません。ブラウザに上手く表示されないデータは、毎回固定ではなく、クリックするタイミングにもより変化してます。(全て正常に動作することもあります)
該当のソースコード
PYTHON
1from flask import Flask, Response, request,render_template 2import queue 3import time 4 5app = Flask(__name__) 6q = queue.Queue() 7 8@app.route('/stream') 9def stream(): 10 def event_stream(): 11 while True: 12 event = "test" 13 data = q.get() 14 print(data) 15 yield "event:{}\ndata:{}\n\n".format(event,data) 16 time.sleep(0.1) 17 return Response(event_stream(), mimetype="text/event-stream") 18 19 20@app.route("/ajax", methods=['POST']) 21def ajax(): 22 if request.method == 'POST': 23 print("キューに追加開始") 24 q.put("処理①") 25 q.put("処理②") 26 q.put("処理③") 27 q.put("処理④") 28 q.put("処理⑤") 29 q.put("処理⑥") 30 q.put("処理⑦") 31 q.put("処理⑧") 32 q.put("処理⑨") 33 q.put("処理⑩") 34 print("キューに追加終了") 35 return "ajax end" 36 37 38@app.route("/") 39def index(): 40 return render_template('index.html') 41 42if __name__ == '__main__': 43 app.run(port=5000, debug=True)
HTML
1<!DOCTYPE html> 2<html lang="ja"> 3 <head> 4 <meta charset="UTF-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 <title>Test</title> 7 <link rel="stylesheet" href="static/style.css" /> 8 <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script> 9 <script defer src="static/script.js"></script> 10 </head> 11 <body> 12 <input type="button" id="btn" value="btn"> 13 </body> 14</html>
javascript
1$(function () { 2 3 var evtSource = new EventSource("/stream"); 4 evtSource.addEventListener("test",function(e){ 5 console.log(e.data); 6 }); 7 8 $("#btn").click(function () { 9 $.ajax({ 10 url: "/ajax", 11 type: "POST", 12 }) 13 .done(function (data) {console.log(data);}) 14 .fail(function () {console.log("Error");}); 15 }); 16 17});
試したこと・疑っていること
- whileの中でsleepを入れると、若干ではあるが気持ち改善するような気がしますが、それでも同様のエラーは依然と起きており、根本的な解決にはいたっておりません。
- ブラウザ側で取得できていない値があるときは、サーバー側のログをみてみると法則として、直前にhttpリクエストが走っていることが多いと気づいたのですが、それを発生させないようなコードの書き方がわからないです。(これが直接的な原因なのかわかりません)
補足情報(FW/ツールのバージョンなど)
・python3.9
・flask
・参考コード:Flaskで簡易版プログレスバー実装して処理の進捗見れるようにしてやんよ!!!
些細なことでも構いませんので、お力添えのほどよろしくお願いいたします。
<2021/1/16 13:15 追記>
app.run()の直前でWSGIRequestHandlerでhttp1.1を指定した結果は下記のようになりました。【参考コード】
python
1WSGIRequestHandler.protocol_version = "HTTP/1.1"
レスポンスヘッダーを見ると、http/1.0からhttp1.1にはなったのですが、Connectionはcloseのままでした。
そして、データの欠落についてですが、まだ改善は見られておりません。
<2021/1/16 14:03 追記>
WSGIRequestHandlerでhttp1.1の指定に加えて、Responseヘッダにkeep-aliveを追加。
python
1resp = Response(event_stream(), mimetype="text/event-stream") 2resp.headers['Connection'] = 'keep-alive' 3return resp
Connectionにkeep-aliveが追加されるようにはなったのですが、Connection:closeは残ったまま。
データの欠落も、まだ改善は見られておりません。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/01/16 04:17
2021/01/16 04:38
2021/01/16 05:13
2021/01/19 07:03
2021/01/19 08:46