使用内联回调

8 投票
2 回答
6124 浏览
提问于 2025-04-17 14:51

我刚接触Twisted,想写一个简单的程序,显示数据库里的名字列表。这是我代码的一部分:

#code from my ContactResource class
def render_GET(self, request):
    def print_contacts(contacts, request):
        for c in contacts:
            request.write(c.name)
        if not request.finished:
            request.finish()
    d = Contact.find() #Contact is a Twistar DBObject subclass
    d.addCallback(print_contacts, request)
    return NOT_DONE_YET

我想问的是:我该怎么改这个方法,让它使用inlineCallbacks这个装饰器呢?

2 个回答

-2

编辑:我没有找到如何将twisted.web和inlineCallbacks结合起来的例子,但这里有两个建议。第一个建议更好,不过我不确定它是否有效。

@inlineCallbacks
def render_GET(self, request):
    contacts = yield Contact.find() 
    defer.returnValue(''.join(c.name for c in contacts)


@inlineCallbacks
def render_GET(self, request):
    contacts = yield Contact.find() 
    for c in contacts:
        request.write(c.name)
    if not request.finished:
        request.finish()
    defer.returnValue(NOT_DONE_YET)
11

一个 render_GET 方法不能返回 Deferred。它只能返回一个字符串或者 NOT_DONE_YET。任何用 inlineCallbacks 装饰的方法都会返回一个 Deferred。所以,你不能用 inlineCallbacks 来装饰 render_GET

当然,你可以在 render_GET 中调用任何你想要的其他函数,包括那些返回 Deferred 的函数。只要在 render_GET 中不返回这个 Deferred,而是把它丢掉就行了(当然,要确保这个 Deferred 不会因为错误而触发,否则你可能会错过一些错误报告...)。

所以,比如说:

@inlineCallbacks
def _renderContacts(self, request):
    contacts = yield Contact.find() 
    for c in contacts:
        request.write(c.name)
    if not request.finished:
        request.finish()


def render_GET(self, request):
    self._renderContacts(request)
    return NOT_DONE_YET

如果你打算用 Twisted 进行一些认真的网页开发,我建议你至少看看 txyogaklein。即使你不想使用它们,它们也能给你一些关于如何组织代码和完成各种常见任务的好主意。

撰写回答