Home > Net >  Streaming data from multiple class functions
Streaming data from multiple class functions

Time:10-25

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
  • Related