I want to display progress in the template while a time-consuming task is underway. I started by having it work on one function.
@app.route('/process', methods=['GET','POST'])
def process():
def test():
for i in range(5):
time.sleep(1)
yield f'data:{i}\n\n'
return Response(test(), mimetype='text/event-stream')
For displaying and stopping once task is done.
$('#process').on('click', e => {
var source = new EventSource('/process');
source.onmessage = (e) => {
$('#result').text(e.data);
if (e.data == '4') {
source.close();
}
}
e.preventDefault();
});
On the click of a button. The element in the template will display '0' to '4' in 1 second intervals.
But I want to display from multiple sources in multiple class functions. Here's what I've attempted so far, having a simplified version just showing the flow of the actual task, displaying progress in one function and outputting the result on the first one:
class Foo:
def __init__(self):
self.bar = 'foobar'
def f1(self):
i = 3
while i != 0:
self.f2(i)
i -= 1
time.sleep(1)
yield f'data:{self.bar}\n\n'
def f2(self, i):
time.sleep(1)
yield f'data:{self.bar}{i}\n\n'
@app.route('/process', methods=['GET','POST'])
def process():
a = Foo()
return Response(a.f1(), mimetype='text/event-stream')
What I expected from this is for the element to display 'foobar3', 'foobar2', 'foobar1', and 'foobar' in 1 second intervals, but what it displayed when I ran this is 'foobar' and no more. It didn't call f2()
.
CodePudding user response:
I guess you want yield from
def f1(self):
i = 3
while i != 0:
yield from self.f2(i)
i -= 1
time.sleep(1)
yield f'data:{self.bar}\n\n
which is really just short hand for
def f1(self):
i = 3
while i != 0:
for f2_val in self.f2(i):
yield f2_val
i -= 1
time.sleep(1)
yield f'data:{self.bar}\n\n