Một giải pháp cơ bản nhưng khả thi (ý chính):
Bạn có thể làm điều này bằng cách chuyển hướng từ tuyến đường sắp xếp công việc, sau đó có thẻ meta làm mới trang đó theo định kỳ. Đầu tiên hãy nhập các thư viện được yêu cầu:
from flask import Flask, redirect, url_for, render_template_string
app = Flask(__name__)
from time import sleep
from rq import Queue
from rq.job import Job
from redis import Redis
Thiết lập các kết nối liên quan đến rq và xác định hàm để chạy:
r = Redis(host='redisserver')
q = Queue(connection=r)
def slow_func(data):
sleep(5)
return 'Processed %s' % (data,)
Sau đó, xác định một mẫu có thể làm mới trang sau mỗi 5 giây:
template_str='''<html>
<head>
{% if refresh %}
<meta http-equiv="refresh" content="5">
{% endif %}
</head>
<body>{{result}}</body>
</html>'''
Chúng tôi cũng sẽ tạo một hàm trợ giúp để trả về mẫu đó với một biến được chèn vào, sử dụng flask render_template_string
. Lưu ý rằng làm mới mặc định là Sai, nếu không được cung cấp:
def get_template(data, refresh=False):
return render_template_string(template_str, result=data, refresh=refresh)
Bây giờ, hãy tạo một tuyến đường sẽ xếp hàng hàm của chúng ta, lấy rq job-id của nó, sau đó trả về chuyển hướng đến result
xem với id
đó . Điều này chỉ nhận đầu vào trong chuỗi URL, nhưng có thể lấy dữ liệu đó từ bất kỳ đâu:
@app.route('/process/<string:data>')
def process(data):
job = q.enqueue(slow_func, data)
return redirect(url_for('result', id=job.id))
Bây giờ, hãy xử lý kết quả thực tế, với sự trợ giúp của rq.Job
vật. Logic ở đây có thể được điều chỉnh, vì điều này sẽ khiến trang được làm mới trên tất cả các giá trị ngoại trừ "finished"
:
@app.route('/result/<string:id>')
def result(id):
job = Job.fetch(id, connection=r)
status = job.get_status()
if status in ['queued', 'started', 'deferred', 'failed']:
return get_template(status, refresh=True)
elif status == 'finished':
result = job.result
# If this is a string, we can simply return it:
return get_template(result)
Nếu trạng thái là "finished"
rồi đến job.result
sẽ chứa giá trị trả về của slow_func
, vì vậy chúng tôi hiển thị điều này trên trang.
Phương pháp này có nhược điểm là gây ra một số yêu cầu đến máy chủ, trong khi chờ hoàn thành công việc. Thẻ làm mới meta có thể hơi khác thường. Nếu bạn đang gửi yêu cầu cập nhật từ Javascript, thì có những giải pháp có thể gửi yêu cầu AJAX trong một khoảng thời gian, mặc dù điều này gặp phải vấn đề nhiều yêu cầu giống nhau.
Giải pháp thay thế là sử dụng websockets hoặc SSE để truyền kết quả của công việc đã hoàn thành tới giao diện người dùng ngay sau khi nó hoàn thành.
CẬP NHẬT:27 tháng 2 năm 2021
Tôi quyết định sử dụng phương pháp SSE để cập nhật giao diện người dùng với trạng thái công việc. Tôi học được rằng rq
có hỗ trợ gốc để cập nhật meta
thuộc tính trong công việc, bằng cách nhập rq.get_current_job
bên trong công việc, sau đó có thể được truy cập bên ngoài sau khi làm mới công việc.
Xem mã trình diễn cho:
Một ví dụ cơ bản với thanh tiến trình (ý chính):