5

tornado.genモジュールのドキュメントから私が理解していることから、 tornado.gen.Task は tornado.gen.Callback と tornado.gen.Wait で構成され、各 Callback/Wait ペアは一意のキーに関連付けられています...

  @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")

したがって、上記のコードは、さまざまな URL からすべての応答を取得します。ここで実際に達成する必要があるのは、1 つの http_client がデータを返したらすぐに応答を返すことです。したがって、「tornadoweb.org」が最初にデータを返す場合、self.write(respose) を実行し、def get() のループは他の http_clients が完了するまで待機し続ける必要があります。tornado.gen インターフェイスを使用してこれを記述する方法に関するアイデア。

私がやろうとしていることの非常にあいまいな実装(および構文的に正しくない)は、次のようになります

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
4

2 に答える 2

4

を使用してはならない場合inline callbacks、つまりgen. またself.render、すべてのコールバックが終了した後に呼び出されます。サーバーからの応答を部分的に返したい場合は、部分的にレンダリングします。

このように考えてください(改善の余地が大きいアイデアです):

  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)
于 2012-08-11T20:32:16.197 に答える
3

これに加えて、実際にはすべての結果を待機し、すべての HTTPClient が応答を返すのを完了すると戻るメソッド WaitAll があります。トルネード ブランチ ( https://github.com/pranjal5215/tornado ) に差分を送信しました。非同期の WaitAll であるクラス WaitAny を追加し、1 つの HTTPClient が結果を返すとすぐに結果を返します。

差分は ( https://github.com/pranjal5215/tornado/commit/dd6902147ab2c5cbf2b9c7ee9a35b4f89b40790e )、( https://github.com/pranjal5215/tornado/wiki/Add-WaitAny-to-make-WaitAll-return-results-徐々に)

使用例:

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() 
于 2012-08-15T15:20:21.340 に答える