1. 程式人生 > >理解Twisted的Deferred機制(一)

理解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回撥地獄囂張,都有方法可以解決。