On 6 Sep, 11:59 pm, firstname.lastname@example.org wrote:
I'd like to start streaming the document as soon as I start receiving the results of the operation, but I'm stumped on how to actually implement this. If I return a deferred from the render method, I cannot fire this deferred until all of the rows have been built up.
Use a recursive generator that yields Deferreds for loading each row.
Here's an example - which I even looked at in a web browser :) - that should help to get you started. (The athena stuff is beside the point, it's just the quickest way I know to get a server serving a Nevow page...)
Warning: I haven't tested this on really large datasets, so it might have disastrous performance consequences. I don't *think* that it will, but I know there are some booby-traps in the rendering pipeline to snare the unwary.
# -- cut here for slow.py -- # Run quickly: twistd -n athena-widget --element slow.SlowElement
from twisted.internet import defer from twisted.internet import reactor from nevow.loaders import stan from nevow.tags import div, directive from nevow.athena import LiveElement from nevow.page import renderer
def deferLater(n, result=None): """ Why isn't this in Twisted yet? Is it? """ d = defer.Deferred() reactor.callLater(n, d.callback, result) return d
def delayedResults(results): """ Yield results.... slowly..... """ yield div[results.pop(0)] if results: def more(result): return delayedResults(results) yield deferLater(2.0).addCallback(more)
class SlowElement(LiveElement): """ Render a list of 1 to 10 really slowly. """ def start(self, ctx, data): """ Give some data, wait for next result... """ return delayedResults(map(str,range(10))) renderer(start) docFactory = stan(div(render=directive("start")))