2014-09-20 45 views
3

最近,我正在學習介紹龍捲風,和我碰到下面的代碼來:進行異步調用時,'yield'在龍捲風中如何工作?

class IndexHandler(tornado.web.RequestHandler): 
    @tornado.web.asynchronous 
    @tornado.gen.engine 
    def get(self): 
     query = self.get_argument('q') 
     client = tornado.httpclient.AsyncHTTPClient() 
     response = yield tornado.gen.Task(client.fetch, 
       "http://search.twitter.com/search.json?" + \ 
       urllib.urlencode({"q": query, "result_type": "recent", "rpp": 100})) 
     body = json.loads(response.body) 

     [...omitted the following code...] 

我曾經瞭解到,yield的關鍵詞是轉向一個共同的功能爲發電機,當它以other = yield foo的形式使用,意味着,「收益foo,並且在向我發送值時,將其他值設置爲該值。」於是,我就在IPython中下面的代碼:

In [1]: result = 'init'  #set a global variable 

In [2]: def test_yield(): 
    ...:  global result 
    ...:  print 'start test...' 
    ...:  result = yield 'foo' 
    ...:  print 'end test...' 
    ...:  

In [3]: t = test_yield() 

In [4]: t.next() 
start test... 
Out[4]: 'foo' #'foo' has been yield to the caller, and blocked 

現在我打印的全球varialbe result,它仍然被稱爲串「初始化」:

In [5]: print result 
init 

然後我叫send()法,發送一個新的字符串yield

In [6]: t.send('new message') 
end test... 
--------------------------------------------------------------------------- 
StopIteration        Traceback (most recent call last) 
/home/chiyu/<ipython-input-6-b86312ad7d0e> in <module>() 
----> 1 t.send('new message') 

StopIteration: 

正如預期的那樣,一個StopIteration升高和輸出的ST環「端測試...」,但現在的全局變量result已經改變:

In [7]: print result 
new message 

Apperantly的yield聲明接受字符串時,我們稱爲send()方法,並指派了新的字符串變量結果。

我的問題是:

回到代碼顯示在頂部,根據該邏輯,

response = yield tornado.gen.Task(client.fetch, 
        "http://search.twitter.com/search.json?" + \ 
        urllib.urlencode({"q": query, "result_type": "recent", "rpp": 100})) 

當方法client.fetch返回,一個Task實例將被創建並yield到來電者,但左側的變量response將不會收到任何內容,因爲沒有send()方法已被執行。我對此很困惑,並徒然搜索。

我會非常感謝您的解釋!

+1

'client.fetch'沒有被調用;它只是被*引用*。 Task()對象會負責實際調用它。 – 2014-09-20 13:16:59

+0

什麼讓你覺得龍捲風不會在你的發電機上使用'send()'? – 2014-09-20 13:17:19

+0

這裏的'client'是什麼,它是'tornado.httpclient.AsyncHTTPClient'的一個實例嗎? – 2014-09-20 13:22:28

回答

4

你是已經瞭解Tornado如何使用生成器來處理異步調用。

我在這裏假設clienttornado.httpclient.AsyncHTTPClient()的一個實例;它的fetch()方法需要回調函數。

tornado.gen.Task對象只需要參考client.fetch方法;你不是在這個時候調用它。您正在構建一個帶有該方法引用和參數的Task()實例,然後生成該實例。

龍捲風然後將運行該Task; Task將依次使用提供的參數加上回調函數調用client.fetch()。然後client.fetch()異步運行,並調用回調。然後將任何傳遞給回調函數的結果記錄爲Task結果。

這個結果然後被髮送到你的IndexHandler.get()發電機send(),從yield Task()表達式返回並分配給response

換句話說,龍捲風確實使用.send()這裏的東西分配給response

2

它的意思是「我放棄了對你的控制;當你有這個未來的結果時再回來」,因此有點像異步解引用操作符。當龍捲風準備就緒時,龍捲風迴應send

請參閱http://tornado.readthedocs.org/en/latest/gen.html以獲得更深入的解釋。