是否判断
An if/else that skips the branch you didn't pick
- on_true
- on_false
- any
ComfyUI executes the whole graph, always. That's the mental model everyone starts with, and it's why "conditional workflows" feel impossible the first time you want one: there's no way to say don't run this. 是否判断 (QG_IfElse) is a node that says exactly that, and it's the cleanest example in the ecosystem of why lazy evaluation matters.
What it actually does
One boolean in. Two value inputs, on_true and on_false, both wildcard. One wildcard output. True passes the first through, false passes the second. Superficially that's a x if cond else y and you could almost fake it with a couple of switches.
The difference is in the execution. Both value inputs are declared lazy, and the node implements the check the backend calls to decide what to evaluate: if the condition is true and on_true hasn't been computed yet, it asks for on_true - and it never asks for on_false. Which means anything hanging off the branch you didn't pick is not executed at all. Not "executed and thrown away". Not executed.
Practical consequences, and this is the part worth internalising:
- A 20 GB model load parked on the untaken branch costs nothing.
- A branch whose upstream is half-wired doesn't error, because it never runs.
- A subgraph that would crash on this input - wrong resolution, wrong clip length, a model that can't do the thing - can sit there inert as long as the condition points elsewhere.
That's a categorically different tool from a passthrough switch, and it's why the port (from yolain's Easy-Use easy ifElse, GPL-3.0) kept the lazy plumbing rather than simplifying it.
Inputs and outputs
boolean(required, default false) - the condition. In practice you wire a boolean output into it (a comparison node, a toggle, a workflow switch), or leave it as a widget and flip it by hand.on_true(wildcard) - what comes out when the condition is true. Not evaluated otherwise.on_false(wildcard) - what comes out when it's false. Not evaluated otherwise.- Output
any- whichever one was selected, same type as the input.
Keep both branches the same type. The node doesn't enforce it - wildcards are wildcards - but the socket label follows the wiring, and if you feed an IMAGE out of one branch and a LATENT out of the other, whichever node consumes any will fail on half your runs. It's the most common way people break this node.
Where it fits in a real workflow
The classic pattern is a model-tier switch: a boolean from a size check or a workflow switch decides whether the graph does the "proper" path or the "fast" path. Because the untaken side is never evaluated, you can keep an experimental branch on the canvas without paying for it - which is a much nicer life than commenting nodes out.
The other pattern is guarding something expensive but optional: an upscale pass that only runs when the base image passed a quality check, an LLM prompt rewrite you only want on the fiddly jobs. Put the expensive thing on on_true and a straight passthrough on on_false.
Pair it with 任意切换 and you can build a surprising amount of control flow out of two nodes: the switch handles "first available", the if/else handles "only if".
Install
Same pack, same two routes. Via Manager, search ComfyUI-QG-Tools:
cd ComfyUI/custom_nodes
git clone https://github.com/live1617/ComfyUI-QG-tools
Restart ComfyUI completely - the console confirms with [QG-tools] v0.9.2 加载完成 | 节点数 24. Zero pip dependencies; the pack's requirements file is comments-only by design, so Manager won't run a pip step. This node ships in the QG-tools/逻辑 category and answers to the search term if, branch or 是否判断.
Where people get burned
Expecting it to be a selector. It isn't - there's no index or dropdown, just a boolean, and a boolean coming from anywhere is fine. If you want to manually choose between three things, you want a switch with a selector instead.
Forgetting the lazy part cuts both ways. Because the untaken branch never runs, its preview nodes never refresh either. People report "my preview is stuck showing an old image" - that's not a bug, that's the branch not executing. Wire your debug preview after the if/else output, not inside a branch.
Assuming it gates caching. It gates execution, not visibility: the node still runs every time the boolean or the taken value changes, and everything upstream of the taken branch runs as usual. It's a branch, not a cache.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| boolean | BOOLEAN | false | Condition. True passes on_true through, false passes on_false. |
| on_true | * | Value passed through when the condition is true. Not evaluated otherwise. | |
| on_false | * | Value passed through when the condition is false. Not evaluated otherwise. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| any | * | — |