理解Twisted的Deferred機制(一)
Twisted作為Python下的非同步網路框架,在非同步機制上與Nodejs很相像,但Twisted已經發展了十多年了。
為了簡化非同步程式設計,Twisted引入了Deferred延遲物件的概念。
Deferred是Twisted非同步框架內部實現的一套callback呼叫的機制,或者可以說是一種設計模式。我們都知道jQuery也有一套Deferred機制,用來簡化非同步程式設計。
Twisted的Deferred差不多也是類似的東東。在本質實現上與Twisted的網路是完全可以獨立應用的,你完全可以理解為是一套介面。
具體怎麼來理解呢,先上程式碼:
from twisted.internet.defer import Deferred from twisted.python.failure import Failure from twisted.internet import reactor, defer def loadRemoteData(callback,errback,url): 此處載入url內容 callback('url資料')或<span style="font-family: Arial, Helvetica, sans-serif;">errback(...)</span> def getRemoteData(): d = defer.Deferred() reactor.callInThread(loadRemoteData,d.callback,d,errback,"http://www.baidu.com") return d def getResult(v): print "result=",v if __name__ == '__main__': d=getRemoteData() d.addCallback(getResult) reactor.callLater(4, reactor.stop); reactor.run()
上述getRemoteData從遠端載入一個url的內容,由於涉及網路操作,因此需要採用非同步操作,也說是我們從遠端載入url資料時不堵塞主執行緒,因此我們呼叫
<pre name="code" class="python"> reactor.callInThread(loadRemoteData,d.callback,"http://www.baidu.com")
在另外一執行緒進行讀取,這樣就不會堵塞主執行緒,而getRemoteData則只是返回一個Deferred物件。Deferred物件提供了addCallback和addErrCallback兩個方法,用來讓你註冊回撥函式。
由於實現的讀取操作是個另外一個執行緒loadRemoteData進行操作,因此getRemoteData方法是不會堵塞的,而是直接返回的。
那當loadRemoteData載入成功時,就執行Deferred物件的callback方法,如果發生錯誤就呼叫Deferred物件的errback方法,這兩個方法實際上是告訴
deferred物件要做的事情已經完成,如果是呼叫callback方法,則deferred物件就會依次執行addCallback新增的callback方法。如果是呼叫errback方法,則deferred物件就會依次執行addErrback新增的callback方法。
大家可以發現deferred的原理與jquery的Deferred,或es6的promise有些像,其本質就是提供一種機制,或者一種約定的操作模式,讓你按統一的形式去進行非同步程式設計而已。
但是大家也可以發現,twisted的deferred機制,也是採用callback 方式,沒有jquery Deferred或es6的promise非同步程式設計模式 先進,不能夠使用像then().then()這樣的鏈式呼叫模式。
在實現使用中很容易就會如同javascript一樣陷入callback回撥地獄中。
好在萬能python不可能讓這callback回撥地獄囂張,都有方法可以解決。