2017-10-30 9 views
3

socket.io JavaScriptクライアントからデータをログに記録するFlask-SocketIO pythonサーバーを作成しました。Socket.IO Emit Sending in Delay

サーバー:

from flask import Flask, render_template 
from flask_socketio import SocketIO 

app = Flask(__name__) 
socketio = SocketIO(app) 

@socketio.on('connect') 
def handle_connect(): 
    print 'Connected' 

@socketio.on('disconnect') 
def handle_disconnect(): 
    print 'Disconnected' 

@socketio.on('start') 
def handle_start(): 
    print 'Start' 

@socketio.on('log') 
def handle_log(data): 
    print('Log: ' + data) 

if __name__ == '__main__': 
    socketio.run(app) 

クライアント:

<script src="socket.io.js"></script> 

<script> 
    function sleep(ms) { 
     var unixtime_ms = new Date().getTime(); 
     while(new Date().getTime() < unixtime_ms + ms) {} 
    } 

    var socket = io.connect('http://127.0.0.1:5000', {'forceNew':true }); 
    socket.on('connect', function() 
    { 
     socket.emit('start'); 
     socket.emit('log', '1'); 
     socket.emit('log', '2'); 
     socket.emit('log', '3'); 

     sleep(3000) 
    }); 
</script> 

代わりのサーバーの印刷 "スタート"、 "ログ:1" を見てすぐに: "3ログ" と "2ログ" を、 。

サーバーは「開始」のみを印刷し、3秒後には他のすべてのメッセージをワンショットで印刷します。

これは私がリアルタイムログを必要とするため問題であり、実行終了時にすべてのログをワンショットで受け取る余裕がありません。

これがなぜ起こっているのか、この単純なログサーバーを実装する正しい方法は何ですか?

+2

'sleep(3000)'コールをコメントアウトすると動作しますか? – Miguel

+0

これは、関数が終了し、関数が終了したときにのみ、他のすべてのemitが起動されるために機能します。私はリアルタイムで、そして機能が終了するときだけでなく、他の発光も必要です。 – Michael

+1

関数が終了するということは無関係です。ここでの鍵は 'sleep()'を呼び出すときにブロックしていることです。 JSは非同期言語なので、ブロックすることはできません。 – Miguel

答えて

-1

実際に眠っているのではなく、忙しく待っているので、使用している機能はJavaScriptにとっては本当に悪いことです。つまり、3秒間CPUが接続されているため、CPUを実行する必要がある他のタスクが遅れることになります。

あなたが何かを行う前に3秒待つ必要がある場合、私はあなたがタイマーオブジェクトを使用することをお勧め:

window.setTimeout(function() { alert('do something!'); }, 3000); 

あなたがタイムアウトを使用して眠る場合は、待機時間中にCPUを解放し、ということであろうJSスケジューラーは、Socket.IOをサポートするものなど、必要な他のタスクにそれを与えることができます。

希望すると便利です。

+0

これは私の質問とは無関係ですが、ポイントは最初の放出(「開始」)が直ちに(リアルタイムで)起こり、他の放出は機能が終了するまで何らかの理由で「つぶれている」ということです。機能が終了してからのみ、他のすべての発光が発生します。 – Michael

+1

downvoteありがとう。非同期システムの仕組みに慣れていないので、 'sleep()'関数が本当に問題である理由を理解することをお勧めします。 – Miguel

+0

私はあなたの助けに感謝しますが、睡眠を使用して私の質問を簡素化するための単なる例でした。私の元のコードはsleepの代わりに "window.location.reload()"を持っています。エミットコールはすぐには発生しません(非同期です)ので、リロードプロセスとエミットコールは競合状態になり、一部は正常にサーバーを呼び出しますが、ページがリロードされたため一部が失われます。私が見たものから、リクエストをバッファリングして(1-n)、特定の時間にしかそれらをフラッシュすることはできません(例えば、関数の終わり)。私は放出を確実にする方法が必要なので、私の質問と単純化として睡眠を使用します。 – Michael