2012-08-10 11 views
5

Da quello che ho capito dai documenti del modulo tornado.gen è che il file tornado.gen.Task comprende tornado.gen.Callback e tornado.gen.Wait con ogni coppia di richiamata/attesa associata a chiavi univoche. ..Tornado Async HTTP restituisce i risultati in modo incrementale

@tornado.web.asynchronous 
    @tornado.gen.engine 
    def get(self): 
     http_client = AsyncHTTPClient() 
     http_client.fetch("http://google.com", 
         callback=(yield tornado.gen.Callback("google"))) 

     http_client.fetch("http://python.org", 
         callback=(yield tornado.gen.Callback("python"))) 

     http_client.fetch("http://tornadoweb.org", 
         callback=(yield tornado.gen.Callback("tornado"))) 
     response = yield [tornado.gen.Wait("google"), tornado.gen.Wait("tornado"), tornado.gen.Wait("python")] 

     do_something_with_response(response) 
     self.render("template.html") 

Così il codice sopra otterrà tutte le risposte dai diversi URL. Ora quello che devo effettivamente realizzare è restituire la risposta non appena un http_client restituisce i dati. Quindi se 'tornadoweb.org' restituisce i dati per primi, dovrebbe eseguire un self.write (respose) e un loop in def get() dovrebbe continuare ad attendere il completamento di altri http_clients. Qualche idea su come scrivere questo usando l'interfaccia di tornado.gen.

Molto vaga implementazione (e sintatticamente corretto) di quello che sto cercando di fare sarebbe come questo

class GenAsyncHandler2(tornado.web.RequestHandler): 
    @tornado.web.asynchronous 
    @tornado.gen.engine 
    def get(self): 
     http_client = AsyncHTTPClient() 
     http_client.fetch("http://google.com", 
          callback=(yield tornado.gen.Callback("google"))) 

     http_client.fetch("http://python.org", 
          callback=(yield tornado.gen.Callback("python"))) 

     http_client.fetch("http://tornadoweb.org", 
          callback=(yield tornado.gen.Callback("tornado"))) 

     while True: 
      response = self.get_response() 
      if response: 
       self.write(response) 
       self.flush() 
      else: 
       break 
     self.finish() 


    def get_response(self): 
     for key in tornado.gen.availableKeys(): 
      if key.is_ready: 
       value = tornado.gen.pop(key) 
       return value 
     return None 

risposta

3

Oltre a questo, in realtà v'è un metodo WaitAll che attende per tutti i risultati e resi, quando tutti HTTPCliens hanno completato dando risposte. Ho presentato il diff nel mio ramo di tornado (https://github.com/pranjal5215/tornado). Ho aggiunto una classe WaitAny che è Async WaitAll e restituisce i risultati non appena un HTTPClient ha restituito il risultato.

Diff è a (https://github.com/pranjal5215/tornado/commit/dd6902147ab2c5cbf2b9c7ee9a35b4f89b40790e), (https://github.com/pranjal5215/tornado/wiki/Add-WaitAny-to-make-WaitAll-return-results-incrementally)

utilizzo

Esempio:

class GenAsyncHandler2(tornado.web.RequestHandler): 
    @tornado.web.asynchronous 
    @tornado.gen.engine 
    def get(self): 
     http_client = AsyncHTTPClient() 
     http_client.fetch("http://google.com", 
          callback=(yield tornado.gen.Callback("google"))) 

     http_client.fetch("http://python.org", 
          callback=(yield tornado.gen.Callback("python"))) 

     http_client.fetch("http://tornadoweb.org", 
          callback=(yield tornado.gen.Callback("tornado"))) 
     keys = set(["google", "tornado", "python"]) 
     while keys: 
      key, response = yield tornado.gen.WaitAny(keys) 
      keys.remove(key) 
      # do something with response 
      self.write(str(key)+"  ") 
      self.flush() 
     self.finish() 
4

E 'caso, quando non si dovrebbe usare inline callbacks, cioè gen. Viene chiamato anche self.render al termine di tutte le richiamate. Se si desidera restituire parzialmente la risposta dal server, renderla parzialmente.

pensare in questo modo (è solo idea con grande sala di miglioramento):

response = [] 
    @tornado.web.asynchronous 
    def get(self): 
     self.render('head.html') 
     http_client = AsyncHTTPClient() 

     http_client.fetch("http://google.com", 
         callback=self.mywrite) 

     http_client.fetch("http://python.org", 
         callback=self.mywrite) 

     http_client.fetch("http://tornadoweb.org", 
         callback=self.mywrite) 

     self.render('footer.html') 
     self.finish() 


    def mywrite(self, result): 
     self.render('body_part.html') 
     self.response.add(result) 
     if len(self.response) == 3: 
     do_something_with_response(self.response) 
Problemi correlati