2016-01-27 2 views
0

Возможно ли создать DeferredList (или что-нибудь подобное), которое запускает все отложенные в определенном порядке?скрученный заказ 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() 

То, что я хотел бы сделать:

  • создать несколько deferreds
  • каждый последующий отсроченного ожидания на предыдущей одной
  • если предыдущий был результат> 20, остановить всю цепочку

EDIT: я могу добиться этого с @inlineCallback декоратором и сделать код синхронным, но я читал, что @inlineCallbacks следует избегать, так что я хотел бы добиться этого с традиционным отсроченным кодом

+0

@inlineCallback не делает код синхронным. Это хак, который используется в других асинхронных фреймах для записи последовательного асинхронного кода. – monoid

ответ

1

Нет ничего плохого в @inlineCallbacks. Причина, по которой вам было предложено избегать @inlineCallbacks, заключается в том, что слишком легко сделать ваш код случайным образом последовательным; когда вы используете Deferred, вам обычно требуется параллелизм, и иногда бывает трудно заметить, что вы отказались от него, если ваш код выглядит заблокированным. Однако, если вы понимаете, как это работает, @inlineCallbacks подходит, если вы хотите его использовать; и если вы на самом деле хотите последовательное поведение, подобное этому, @inlineCallbacks является совершенным.

+0

Я вижу, и после поиска по Twisted документации я обнаружил «task.Cooperator», он, казалось, достиг точно того, что мне нужно было сделать. Вы предпочли бы использовать '@ inlineCallbacks' или' Cooperator' для достижения этого? – kitensei

+0

Любой из них в порядке; это более стильный выбор в этот момент. – Glyph

Смежные вопросы