扭曲有序的DeferredList

时间:2016-01-27 10:49:00

标签: python asynchronous twisted

是否可以创建以定义的顺序运行所有延迟的DeferredList(或类似的东西)?

我需要运行一个延迟列表,但理想情况下,延迟应该等待前一个,因为它可以改变下一个延迟结果:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""

"""

from __future__ import division, absolute_import, \
    print_function, unicode_literals

from twisted.internet import defer, reactor


def multiply(n):
    if n == 3:
        import time
        time.sleep(1)
    print(n * 10)
    return n * 10


def stopIfResultIsAbove20(n):
    if n > 20:
        print('result is above 20, i would like to stop the following deferreds')
        raise Exception('The result is above 20, cancelling the other deferreds')
    return n


def onSuccess(result):
    print(result)
    return result


def onError(failure):
    print('failed !')
    pass

requests = []
for n in range(0, 6):
    d = defer.Deferred()
    d.addCallback(multiply)
    d.addCallback(stopIfResultIsAbove20)
    if n == 3:
        from twisted.internet import threads
        threads.deferToThread(d.callback, n)
    else:
        reactor.callLater(0, d.callback, n)
    requests.append(d)

dl = defer.DeferredList(requests,
                        fireOnOneErrback=True)
dl.addCallbacks(onSuccess, onError)
dl.addBoth(lambda _: reactor.stop())

reactor.run()

我想做什么:

  • 创建多个延迟
  • 以下各项延迟等待前一次
  • 如果上一个有结果> 20,停止所有链条

编辑:我可以使用@inlineCallback装饰器实现此目的并使代码同步,但我已经读过@inlineCallbacks应该避免,所以我&# 39;我希望用传统的延期代码实现这一目标

1 个答案:

答案 0 :(得分:1)

@inlineCallbacks没有错。您被告知要避免@inlineCallbacks的原因是,您的代码很容易像这样顺序排列;当您使用Deferred时,您通常需要并行性,有时很难注意到如果您的代码看起来阻塞,您就会放弃它。但是,如果您了解它的工作原理,只要您想使用它,@inlineCallbacks就可以了;如果您实际上想要这样的顺序行为,那么@inlineCallbacks就是完美的。