javascript 如何在flask通过socketIO执行任务时使用一些更新来更新HTML页面

xoefb8l8  于 2023-01-29  发布在  Java
关注(0)|答案(1)|浏览(188)

我有一个基本的flask脚本,运行一个简单的ping命令通过子进程上的IP输入的用户。然而,ping去3包,有没有办法让用户知道,该进程正在进行,而他等待通过socketIO功能flask?
现在,为了让用户知道后台正在发生一些事情,我设置了setTimeout函数,以在设定的时间间隔更改按钮文本。
问题是使用来自服务器的内容更新此按钮文本,如**“正在处理.....正在ping $IP..已通过socketIO接收到$NUMBER个数据包“**,这可能吗?

from flask import Flask,render_template,request,redirect,session
import subprocess
from flask_socketio import SocketIO
async_mode = None
app = Flask(__name__)
socket_ = SocketIO(app, async_mode=async_mode)

app.secret_key = "sdfwq34qweds"

@app.route('/')
@app.route('/home')
def home():
    return render_template('home.html',sync_mode=socket_.async_mode)

@app.route('/about')
def about():
    return render_template('about.html')

@app.route('/contact')
def contact():
    return render_template('contact.html')

@app.route('/result' ,methods=['POST','GET'])
def result():
    if request.method == "POST":
        ip1=request.form.get('ip')
        ticket=request.form.get('tic')
        starttime=request.form.get('stime')
        endtime=request.form.get('etime')
        session["ip2"]=request.form.get('ip')
        session["ticket2"]=request.form.get('tic')
        session["starttime2"]=request.form.get('stime')
        session["endtime2"]=request.form.get('etime')
        output=subprocess.Popen(["/usr/bin/python3.8 /u0/sn/dev_scripts/process.py -i "+str(ip1)+" -t "+str(ticket)+" -f "+str(starttime)+" -e "+(endtime)],shell=True,stdout=subprocess.PIPE)
        output.wait()
        out=output.communicate()[0]
        ec=output.returncode
        return render_template('result.html',sync_mode=socket_.async_mode,out=out.decode())

if __name__ == '__main__':
    socket_.run(app,host='0.0.0.0',port=8080,debug=True)

我的主页

root@prod-nexus-app01:/u0/sn/dev_nexus# cat templates/home.html
{% extends 'architecture.html' %}
{% block title %}
<title>LaunchPad</title>
{% endblock %}

<body>
  {% block head %}
  <h1 class="display-1" style="text-align: center;">PING TESTER</h1>
  <blockquote class="blockquote">
  </blockquote>
  <figure style="text-align:center;">
    
  </figure>
  {% endblock %}

  {% block content %}
  <form id="nexus"  action="/result"  method="POST">
  <div class="form-floating mb-3 animate__animated animate__fadeInDown">
    <input type="integer"  name="ip" id='ipadd'  placeholder="8.8.8.8"  class="form-control" >
    <label for="ip">Machine IP</label>
  </div>
  <div class="form-group form-floating mb-3 animate__animated animate__fadeInDown">
    <input  class="form-control input-lg" type="datetimepicker"  required="required" placeholder="YYYY/MM/dd-hh:mm" id="fromdatetime"  name="stime" autocomplete="off">
    <label for="stime">Start Time</label>
    <script src="../static/js/flatpickr"></script>
    <script>
        $('#fromdatetime').flatpickr({
       //step:1,
        //format: 'Y/m/d-H:i',
        //maxTime: "now" ,
        //maxDate: "today",
        //minDate: new Date().setDate(new Date().getDate() - 2),
                    //defaultTime: '00:00',
       //altInput:true,
  enableTime: true,
        //showAlways: true,
        time_24hr: true,
        dateFormat: "d/m/Y/H:i",
        allowInput: true,
        //maxDate:"today",
       minuteIncrement:30,
       // minDate:new Date().setDate(new Date().getDate() - 2),
       });
 </script>
</div>

<div class="form-group form-floating mb-3 animate__animated animate__fadeInDown">
    <input  class="form-control input-lg" type="datetimepicker"  required="required" placeholder="YYYY/MM/dd-hh:mm" title="Ending Time-frame"   id="endtime"  name="etime" autocomplete="off">
  <label for="etime">End Time</label>
    <script type='text/JavaScript'>
              $('#endtime').flatpickr({
       //step:1,
        //format: 'Y/m/d-H:i',
        //maxTime: "now" ,
        //maxDate: "today",
        //minDate: new Date().setDate(new Date().getDate() - 2),
                    //defaultTime: '00:00',
        enableTime: true,
        showAlways: true,
        time_24hr: true,
        dateFormat: "d/m/Y/H:i",
        allowInput: true,
        //maxDate:"today",
        minuteIncrement:30,
      //  minDate:new Date().setDate(new Date().getDate() - 2),
       });
     </script>
  </div>
  <input  id= "submit_lead"   onClick = "changeText()"  type="submit" class="btn inputdisabled btn-dark animate__animated animate__fadeInDown" value="Execute ...">
<script>

### FOR NOW THIS WILL JUST UPDATE THE BUTTON TEXT ACCORDING TO TIME ELAPSED ###

 $(document).ready(function(e) {
  $('#nexus').submit(function() {
    var txt = $('#submit_lead');
    txt.val("Fetching logs...");
          setTimeout(function(){txt.val("Taking longer than 60s..")},60000)
    setTimeout(function(){txt.val("100 Secs elapsed, this may take a while ....")},100000)
          setTimeout(function(){txt.val("200s elapsed,This is taking longer than we thought ... ")},200000)
      setTimeout(function(){txt.val("300s elapsed,but we are still on it!")},300000)
      setTimeout(function(){txt.val("400s elapsed,hang tight!... ")},400000)
      setTimeout(function(){txt.val("500s elapsed,Either Slow speeds or large file size!... ")},500000)
      setTimeout(function(){txt.val("600s elapsed,Logs exceeding several Gigs")},600000)
      setTimeout(function(){txt.val("700s elapsed,likely an overloaded GHost")},700000)
      setTimeout(function(){txt.val("800s elapsed...Hold on")},800000)
      setTimeout(function(){txt.val("900s elapsed....")},900000)
  });
});
</script>
    </form>

  {% endblock %}

  </body>
jvlzgdj9

jvlzgdj91#

要进行实时更新,您需要做两件事:

  • 一种从子流程增量获取信息的方法
  • 在服务器上继续子进程时将更新推送到浏览器的方法

第一个要求可以通过打开子进程并使用迭代器读取其stdout来实现,而不是等待进程完成。
第二个需求可以通过websocket来实现,它从服务器发出更新并在浏览器上捕获它们。
下面是一个简单一点的例子,但希望能给出一个想法。
服务器端代码:

from flask import Flask, render_template
from flask_socketio import SocketIO, emit, disconnect

import subprocess

async_mode = None

app = Flask(__name__)

socket_ = SocketIO(app, async_mode=async_mode)

@app.route('/')
def index():
    return render_template('index.html',
                           sync_mode=socket_.async_mode)

@socket_.on('do_task', namespace='/test')
def run_lengthy_task(data):
    try:
        proc = subprocess.Popen(['ping', '127.0.0.1', '-c', data['count']], bufsize=0, stdout=subprocess.PIPE)
        for line in iter(proc.stdout.readline, b''):
            emit('task_update', { 'data': line.decode('utf-8')[:-1] })
        proc.stdout.close()
        proc.wait()
        result = proc.returncode
        emit('task_done', {'result': result})
        disconnect()
    except Exception as ex:
        print(ex)

if __name__ == '__main__':
    socket_.run(app, host='0.0.0.0', port=80, debug=True)

客户端代码:

<!DOCTYPE HTML>
<html>
<head>
    <title>Long task</title>
    <script src="https://code.jquery.com/jquery-3.6.3.js"></script>
    <script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
    <script type="text/javascript" charset="utf-8">
         $(document).on('click', '.widget input', function (event) {
            namespace = '/test';
            var socket = io(namespace);

            socket.on('connect', function() {
                $('#messages').append('<br/>' + $('<div/>').text('Requesting task to run').html());
                socket.emit('do_task', {count: '10'});
            });
            socket.on('task_update', function(msg, cb) {
                $('#messages').append('<br/>' + $('<div/>').text(msg.data).html());
                if (cb)
                    cb();
            });
            socket.on('task_done', function(msg, cb) {
                $('#messages').append('<br/>Result' + $('<div/>').text(msg.result).html());
                if (cb)
                    cb();
            });
            event.preventDefault();
        });
    </script>
</head>
<body>
    <div class="widget">
        <input type="submit" value="Click me" />
    </div>
    <h3>Messages</h3>
    <div id="messages" ></div>
</body>
</html>

相关问题