Skip to content

Batch

batch body groups writes and defers effects until the outermost batch ends. Several writes produce one run per effect, using the final values. batch returns the body's result.

Memos still refresh when read inside a batch, using the writes made so far.

Test your understanding

After both names change, what does full.Value return inside the batch? When does the effect log the new name, and when is "batch result" logged?

let batchLog =
    use graph = new Graph ()
    use _ = graph.Activate ()
    let first = createSignal "Ada"
    let last = createSignal "Lovelace"
    let full = createMemo (fun _ -> $"{first.Value} {last.Value}")
    let log = ResizeArray ()
    createEffect (fun () -> log.Add $"effect: {full.Value}")

    let result =
        batch (fun () ->
            first.Value <- "Grace"
            last.Value <- "Hopper"
            log.Add $"memo inside the batch: {full.Value}"
            "batch result")

    log.Add result
    List.ofSeq log

batchLog |> List.iter (printfn "%s")
Answer
effect: Ada Lovelace
memo inside the batch: Grace Hopper
effect: Grace Hopper
batch result

Reading full.Value refreshes the memo inside the batch. The effect runs when the batch ends, before batch returns its result to the caller.

In the map, two separate writes run the effect twice. The same two writes in a batch run it once.

Flushing early and handling exceptions

flush () runs queued effects immediately, including inside a batch.

A batch that throws still ends. Later writes flush normally, and effects queued by the failed batch's writes run at the next flush.

Reading effect output

Test your understanding

The signal changes to 5 inside the batch. What is mirrored inside the batch, and after it ends?

let sideEffectInsideBatch, sideEffectAfterBatch =
    use graph = new Graph ()
    use _ = graph.Activate ()
    let count = createSignal 0
    let mutable mirrored = 0
    createEffect (fun () -> mirrored <- count.Value)

    let inside =
        batch (fun () ->
            count.Value <- 5
            mirrored)

    inside, mirrored

printfn "inside the batch: %d, after the batch: %d" sideEffectInsideBatch sideEffectAfterBatch
Answer
inside the batch: 0, after the batch: 5

The effect updates mirrored only when the batch ends.

Edit this page