ComfyUI Node

Output

The 'finally' clause of your ComfyUI batch loop

By teddy1565·Created 5 months ago·Updated 5 months ago· 0
Output
    • output_list
    emitter_result
    key_id
    reset

    Output (class AsyncOutputCallback) is where the AsyncOutput family actually pays off. The Collection node has been stashing strings into a list for N runs; the Emitter has been counting; and this node is the Promise.all(...).then(...) - the callback that finally receives the whole list and hands it to the rest of your graph.

    But it's also the node that explains how this pack does "conditional execution," which is the part beginners bounce off. The trick is comfy_execution.graph.ExecutionBlocker. ComfyUI has no if statement, but a node can return an ExecutionBlocker instead of a real value, and ComfyUI then skips everything downstream of it for that pass. That's not an error - the run continues, the other branches still execute, only the blocked branch stands down. Callback returns a blocker whenever emitter_result is false, meaning "the batch isn't done yet, don't run the join step." The README states it plainly: if the received value is false, "the subsequent downstream process will be blocked directly."

    How it works

    On every pass it looks at emitter_result. False → ExecutionBlocker, downstream doesn't run. True → it pulls ASYNC_OUTPUT_STORAGE_DATA[key_id] (the accumulated list), returns it as output_list, and deletes the record so a later run can collect fresh. If the key_id has no data at all, it blocks too rather than erroring.

    The inputs that matter

    • emitter_result (BOOLEAN, forced input) - wire this from an AsyncOutputEmitter's emit_result output. That's the whole signal.
    • key_id (STRING) - must match the Collection and Emitter you're working with. Same key or nothing lines up.
    • reset (BOOLEAN, optional) - deletes the stored list for this key and blocks. Handy for clearing a collection mid-run.

    Output: output_list (LIST) - the accumulated strings, in the order the Collection nodes appended them. Feed it into a join node, a "String List To String" converter, or anything else that eats a LIST.

    Installing it

    Zero dependencies, no model files. ComfyUI Manager → search "AsyncOutput" → install, or:

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

    Restart. It lives under AsyncOutput/Deprecated(ComfyUI NOT Turing complete)/String.

    Where people get burned

    Two gotchas, both worth memorizing. First, if you see downstream nodes "just not running" with no error, that's the blocker doing its job - check whether emitter_result is actually true that pass. Second, the data is deleted after read: if your workflow re-executes the callback later in the same run (say, a second pass hits it), there's nothing left and it blocks. That's by design - this is a one-shot gather, not a persistent buffer.

    And the standing caveat that applies to the whole pack: the author marks the AsyncOutput family deprecated because ComfyUI isn't really Turing-complete in the way this pattern wants it to be. All the shared state lives in process memory, gets auto-wiped at the start of each run by default, and disappears on restart. For a one-run batch loop it's fine. For anything you expect to remember its own history, look at the non-deprecated BatchIteratorStringCallback, which does the same gather - but notably does not delete the data after reading it.

    CategoryAsyncOutput/Deprecated(ComfyUI NOT Turing complete)/String

    Inputs (3)

    NameTypeDefaultDescription
    emitter_resultBOOLEAN
    key_idSTRING
    resetoptBOOLEAN

    Outputs (1)

    NameTypeDescription
    output_listLIST