AsyncOutput
Simple collect all batch output, then convert to a string list, like ECMAScript Promise.all
Nodes (18)
The 'finally' clause of your ComfyUI batch loop
Park every string a batch run produces, then do something with all of them later
Join a list of strings
A 'do it once after N runs' gate for your ComfyUI graph
The switch that decides whether AsyncOutput forgets everything between runs
The 'clear the AsyncOutput brain' button for when your loop goes weird
A one-shot 'workflow just started' pulse, spelled Singal
Feed one prompt per generation, paced by a loop, without a scheduler node
A counter your other workflow can feed, so a loop knows how far along it is
Read the loop's odometer and decide whether to keep going
Raise an error on purpose when a signal fires
The BatchIterator 'forget everything' node — and yes, it nags you on purpose
Queue a list of prompts and let each run grab the next one, automatically
Peek inside the BatchIterator's hidden memory while your loop runs
Read the gathered strings when the emitter says it's time
The BatchIterator family's 'stash this string' node
Count ticks, fire once when you hit the target, and (bonus) abort on -999
The clean copy of the list-to-string join utility — use this one, not the deprecated twin
��# ComfyUI-AsyncOutput
Simple Source Code
class AsyncOutputCollectionNode:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"incoming_input": ("STRING", { "forceInput": True }),
"key_id": ("STRING", {})
},
"hidden": {
"unique_id": "UNIQUE_ID"
}
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("passthough_output",)
CATEGORY = f'{MAIN_CATEGORY}/String'
FUNCTION = "collect"
def collect(self, incoming_input, key_id, unique_id):
global ASYNC_OUTPUT_STORAGE_DATA
if key_id == "":
raise Exception("ERROR: key_id property not set.")
if key_id not in ASYNC_OUTPUT_STORAGE_DATA:
ASYNC_OUTPUT_STORAGE_DATA[key_id] = []
ASYNC_OUTPUT_STORAGE_DATA[key_id].append(incoming_input)
return (incoming_input,)
@classmethod
def IS_CHANGED(s, incoming_input, key_id, unique_id):
return float('nan')
Intro
Simple collect all batch output, then convert to a string list
Like ECMAScript Promise.all
const tasks_queue: Array<Promise<string>> = [];
for (let i = 0; i < n; i++) {
const task = new Promise<string>((resolve, reject) => {
/* Your jobs, just a mock, */
});
tasks_queue.push(task);
}
/*
results will be an Array<string>
*/
Promise.all(tasks_queue).then((results) => {
const ffmpeg_concat_input_str = results.join("\n");
// others
})
Parmeters
- key_id: persistence memory dict key
Node
- String
- AsyncOutputCollect(Collection)
- Receive other node 'string' output, persistence memory
- Output is 'string', passthrough your input
- AsyncOutputEmitter(Conditions)
- If conditions is true, Output Boolean, else always false.
- AsyncOutputCallback(Output)
- Receive Emitter Output, If true, will output dict[key_id], then delete dict[key_id]
- If the received value is false, then the subsequent downstream process will be blocked directly.
- (comfy_execution.graph.ExecutionBlocker(None), )
- AsyncOutputCollect(Collection)
- Utils
- String List To String
- Convert String List to String
- String List To String
Others (use JS illustrate)
String List to String
const string_list = ["abc", "edf", "jqk"];
const str = string_list.join("<your_input>");
AsyncOutputCollect(Collection)
const collect_list = [];
for (let i = 0; i < n; i++) {
const task = new Promise();
collect_list.push(task);
}
AsyncOutputEmitter(Conditions)
const collect_list = [];
const spec_task_n = 10;
const mode = "exact";
const e = new EventEmitter();
function* collect_task(collect_list) {
for (let i = 0; i < n; i++) {
const task = new Promise();
collect_list.push(task);
yield i;
}
}
current_exec = collect_task(collect_list);
let it = current_exec.next();
if (mode === "exact") { // exact mode
while (it.done == false && it.value != spec_task_n) {
it = current_exec.next();
e.emit("trigger_result", false);
}
} else if (mode === "greater_than_or_equal") { // greater_than_or_equal mode
while (it.done == false && it.value <= spec_task_n) {
it = current_exec.next();
e.emit("trigger_result", false);
}
}
if (it.value == spec_tack_n) {
e.emit("trigger_result", true);
}
AsyncOutputCallback(Output)
const comfy_eventloop_emitter = new EventEmitter();
e.on("trigger_result", (trigger_signal) => {
if (trigger_signal === true) {
const str_list = callback();
comfy_eventloop_emitter.emit("next", str_list);
}
});