Maison > Questions et réponses > le corps du texte
我知道tornado可以用如下方式,同时并发n个请求:
response1, response2,... responsen = yield [http_client.fetch(url1) , http_client.fetch(url2), ...... ,http_client.fetch(url2) ]
等到n个请求都响应了之后,会返回给程序控制权,那么我的问题是:
1.如果我想其中一个有结果了,就返回yield继续执行,应该怎么实现?
2.如果我要让其中i个请求有结果了就返回呢?
三叔2016-10-22 15:55:11
手头没有电脑,先提供一点思路,一会儿验证一下
ioloop的add_future方法可以为future添加callback,先获取http_client的future,然后用add_future方法添加callback,最后再封装成一个新的future,yield新的future就可以了。
伪代码如下
def get_first_result(futures): ret = tornado.gen.Future() def on_result(finished_future): if ret.done(): return if finished_future.exception(): return ret.set_result({"index": futures.index(finished_future), "result": finished_future}) for i in futures: ioloop.add_future(i, on_result) return ret
测试了一下,功能可以实现
使用的时候可以
@tornado.gen.coroutine def get_baidu(): f1 = http_client.fetch("http://www.google.com") f2 = http_client.fetch("http://www.google.com") f3 = http_client.fetch("http://www.google.com") f4 = http_client.fetch("http://www.baidu.com") futures = [f1, f2, f3, f4] result = yield get_first_result(futures) print(result['result'].body) print(result['index']) print("resolved future " + str(futures[result['index']]))
题主的第二个要求没看懂,如果第i个请求返回,就返回yield,那直接yield第i个请求就好了,其他的请求不用yield。
后续如果想继续等待下一个future返回,还可以
futures.pop(result['index']) result = yield get_first_result(futures)
第二版
def get_first_result(futures, count=1): ret = tornado.gen.Future() results = [] def on_result(finished_future): if ret.done(): return if finished_future.exception(): return results.append({"index": futures.index(finished_future), "result": finished_future}) if len(result) == count: ret.set_result(results) for i in futures: ioloop.add_future(i, on_result) return ret