0

这是来自“Twisted Network Programming Essential”的一个例子:

from twisted.internet import reactor
from twisted.internet.defer import Deferred
from twisted.internet.protocol import Protocol
from twisted.web.client import Agent

import sys

from random import random

class ResourcePrinter(Protocol):
    def __init__(self, finished):
        self.finished = finished

    def dataReceived(self, data):
        print data

    def connectionLost(self, reason):
        self.finished.callback(None)

def printResource(response):
    # Nothing added to this 'finished'
    finished = Deferred()
    response.deliverBody(ResourcePrinter(finished))
    return finished

def printError(failure):
    print >>sys.stderr, failure

def stop(result):
    reactor.stop()

if len(sys.argv) != 2:
    print >>sys.stderr, 'Usage'
    exit(1)

agent = Agent(reactor)
d = agent.request('GET', sys.argv[1])
d.addCallbacks(printResource, printError)
d.addBoth(stop)

reactor.run()

但既然它从来不呼入addCallback()finishedprintResource()为什么stop()最后会被呼入connectionLost()呢?

4

2 回答 2

2

这是使用称为“链接”的功能,记录在http://twistedmatrix.com/documents/current/core/howto/defer.html#auto13

于 2013-06-02T14:37:15.533 回答
-1

实际上,它不需要再添加任何回调。它添加了已经听到:

self.finished.callback(None)

所以,让我们看的更仔细。代码指针到达听到:

d.addCallbacks(printResource, printError)

当您查看 printResource 代码块时,它返回一个延迟作为返回值。因此,在此延迟对象获得其结果之前,数据传递将继续进行,直到获得连接丢失事件(由协议覆盖方法捕获)并且最后一步或回调导致完成(延迟)对象,给出其结果。

Main deferred -> add callback -> callback by coming responses-> |
                                                                |
                                                                 -> new deferred -> Receiving data ... til con lost -> add callaback (get result directly)|
                                                                                                                                                          |-> add last callback > stop

关键是,当返回值是一个deferred时,直到得到这个deferred对象的结果,主流程才会继续。

于 2014-06-08T23:28:02.387 回答