To avoid calling a view update once for every synchronous state assignment, collect top-level changes and schedule a single update with queueMicrotask(). The pattern below merges pending values and uses a flag to prevent redundant scheduling. It can reduce repeated update calls in this example, but it is not a transaction system or a guarantee against visible flicker.
Why several assignments can trigger repeated updates
In a simple reactive template system, a Proxy can intercept each assignment to a state object. If its set handler immediately calls the template’s update function, a controller that changes several properties synchronously can invoke that function several times in succession.
As an Amazon Associate I earn from qualifying purchases.
For example, code might assign $scope.name = "Mario" and then replace it with a longer computed value. An immediate update after the first assignment could render the intermediate value before the second update runs. That is a possible visual effect, not a measured or inevitable flicker; what appears depends on the surrounding implementation and browser work.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
What a microtask changes
queueMicrotask() defers a callback until after the current task has completed and before control returns to the browser event loop. MDN notes that microtasks can be useful for work that needs to happen just before rendering, but this ordering does not mean rendering is complete or guarantee that a user will never see an intermediate state. See MDN’s queueMicrotask() reference and microtask guide.
#1 Best Overall
Instead of updating immediately, the setter can add each change to a shared pending object and arrange one callback to process that object. Synchronous assignments made before the callback runs are then coalesced into one update call.
Implement a pending-change batch
Keep the pending changes and scheduling flag in the same scope as the scheduling function so each intercepted assignment shares them:
Rank #2
let pendingChanges = {};
let isScheduled = false;
function scheduleUpdate(change, updateFn) {
Object.assign(pendingChanges, change);
if (isScheduled) return;
isScheduled = true;
queueMicrotask(() => {
updateFn(pendingChanges);
pendingChanges = {};
isScheduled = false;
});
}
How the batch is formed
Object.assign(pendingChanges, change)copies each new change into the pending object. If multiple synchronous changes use the same key, the later value overwrites the earlier pending value.isScheduledensures that additional assignments join the existing batch instead of queuing a separate microtask for each one.- When the callback runs, it passes the combined changes to
updateFn, replaces the pending object with an empty one, and clears the flag so a later batch can be scheduled.
Connect the Proxy setter
Have the Proxy’s set handler schedule the change rather than immediately call the view update. A minimal sketch is:
const scope = new Proxy(initialState, {
set(target, key, value) {
target[key] = value;
scheduleUpdate({ [key]: value }, update);
return true;
}
});
Here, initialState and update represent the state object and template-update function in your implementation. The important change is that every setter contributes a change to the pending batch, while the scheduler invokes update once for that batch.
What this pattern does not cover
This example observes assignments to top-level properties intercepted by the Proxy. It does not, as written, track a nested mutation such as $scope.person.name = "Mario" or changes inside an array. Those require additional observation logic; batching the top-level setter does not automatically make nested objects or arrays reactive.
Nor is the batch a general transaction: it combines captured changes before the queued callback executes, with later values replacing earlier ones for the same key. It does not establish atomicity across arbitrary application work.
Rank #4
Check that coalescing works
For a small verification exercise, count calls to update, then make several synchronous assignments to top-level properties. The expected behavior for this scheduler is one update call for the assignments collected before its microtask runs, with the pending object holding the latest value for any repeated key. This checks the batching logic; it is not a performance benchmark.
Free tools Windows power users keep installed
One-click scans. No signup required.
Quick Recap
Best Value
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




