Nodes/AsyncOutput/Conditions
ComfyUI Node

Conditions

A 'do it once after N runs' gate for your ComfyUI graph

By teddy1565·Created 5 months ago·Updated 5 months ago· 0
Conditions
    • count
    • emit_result
    touch
    modeexact
    key_id
    step1
    conditions1
    reset

    Conditions (class AsyncOutputEmitter) is the counter that decides when a batch is "done" in the AsyncOutput pack. Each time you nudge it, it counts. When the count hits the number you asked for, it fires emit_result = true exactly once and re-arms itself. It's the Promise.all orchestrator in this family: the author's README describes it as an EventEmitter that keeps emitting false until the Nth task finally flips the signal.

    Where it earns its keep: you have a loop that generates N images, each run touching a AsyncOutputCollect node to stash a string. You don't want the "combine all N results" step to run until the loop is genuinely finished. Drop an Emitter in the loop, wire its emit_result into AsyncOutputCallback, and downstream only executes on the run where the count lands on your condition.

    How it works

    State lives in a process-wide dict (ASYNC_OUTPUT_COUNTER) keyed by key_id. When touch is true the counter advances by step. When the counter matches (or exceeds, depending on mode), it returns emit_result = true and deletes the counter record - that delete is what makes it one-shot instead of firing on every later pass. IS_CHANGED returns nan, so the node always executes; the author needs it to run every pass to notice the count.

    The inputs that matter

    • touch (BOOLEAN, forced input) - the pulse. Wire a boolean from your loop here; a false touch just reports the current count, it doesn't advance it.
    • key_id (STRING) - must match the Collection/Callback key.
    • conditions (INT, default 1) - the target count. This is the number you actually think about.
    • mode - exact (fire only when count == conditions) or greater_than_or_equal (fire at the first pass that reaches it).
    • step (INT, default 1) - how much each touch adds. Set it higher if one run represents several units of work.
    • reset (BOOLEAN, optional) - zeroes the counter without firing.

    Outputs: count (INT) tells you the current count, and emit_result (BOOLEAN) is the one you wire into the Callback. The tooltips in the schema describe them as "Current Count Value" and "if count == conditions, return true. then remove this record" - the removal part is the behavior that catches people off guard.

    Installing it

    The pack installs clean with zero dependencies - nothing to pip install, no model files. In ComfyUI Manager search "AsyncOutput", or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/teddy1565/ComfyUI-AsyncOutput
    

    Restart and it appears under AsyncOutput/Deprecated(ComfyUI NOT Turing complete)/String.

    Where people get burned

    The category name isn't sarcasm - the author flags this family as deprecated because ComfyUI doesn't truly support mutable state across a workflow's execution, and it shows in the sharp edges. The whole memory store is auto-wiped at the start of every run unless you disable that with AsyncOutputGlobalAutoReset, and it all lives in process memory, so restart = empty. Also note the record is deleted the moment it fires: if the condition is 1 and you touch it once, that's it for the run - a second trigger on a later run starts a fresh count. If your emitter never fires, the first thing to check is whether auto-reset is eating the counter between touches.

    The maintained sibling family has a near-identical node, BatchIteratorStringEmitter - same idea, fewer modes (== / >= only), and it doesn't delete its record after firing, which makes it more forgiving in loops.

    CategoryAsyncOutput/Deprecated(ComfyUI NOT Turing complete)/String

    Inputs (6)

    NameTypeDefaultDescription
    touchBOOLEAN
    modeCOMBOexact2 options: exact, greater_than_or_equal
    key_idSTRING
    stepINT1
    conditionsINT1
    resetoptBOOLEAN

    Outputs (2)

    NameTypeDescription
    countINTCurrent Count Value
    emit_resultBOOLEANif count == conditions, return true. then remove this record