Repository: sveltejs/svelte
File: packages/svelte/src/internal/client/reactivity/batch.js (JavaScript)

Code before:
			// that will run eagerly whenever the expression changes
			var previous_batch_values = batch_values;

			try {
				batch_values = null;
				value = fn();
			} finally {
				batch_values = previous_batch_values;
			}

			return;
		}

		// the second time this effect runs, it's to schedule a
		// `version` update. since this will recreate the effect,
		// we don't need to evaluate the expression here
		if (!eager_flushing) {
			eager_flushing = true;
			queue_micro_task(eager_flush);
		}
	});

	initial = false;

	return value;
}

/**
 * Forcibly remove all current batches, to prevent cross-talk between tests
 */
export function clear() {
	batches.clear();
}


Review comment (performance):
I wonder if this will yield more fine-grained updates. Right now one source is shared across all eager states, this would make it one source per eager state, so a `$state.eager(...)` of a value that wasn't touched wouldn't run. It won't make much of a difference as soon as it's a changed value though, since then it will rerun for each parallel batch that exists.


```suggestion
/** @type {Source<number>[] | null} */
let eager_flushing = null;

function eager_flush() {
	try {
		flushSync(() => {
			/** @type {Source<number>[]} */ (eager_flushing).forEach((version) => {
				update(version);
			});
		});
	} finally {
		eager_flushing = null;
	}
}

/**
 * Implementation of `$state.eager(fn())`
 * @template T
 * @param {() => T} fn
 * @returns {T}
 */
export function eager(fn) {
	var version = source(0);
	var initial = true;
	var value = /** @type {T} */ (undefined);

	get(version);

	inspect_effect(() => {
		if (initial) {
			// the first time this runs, we create an inspect effect
			// that will run eagerly whenever the expression changes
			var previous_batch_values = batch_values;

			try {
				batch_values = null;
				value = fn();
			} finally {
				batch_values = previous_batch_values;
			}

			return;
		}

		// the second time this effect runs, it's to schedule a
		// `version` update. since this will recreate the effect,
		// we don't need to evaluate the expression here
		if (!eager_flushing) {
			eager_flushing = [];
			queue_micro_task(eager_flush);
		}
		eager_flushing.push(version);
	});

	initial = false;

	return value;
}
```

I tested with this component and the PR does 12 logs when clicking all three quick enough, with the suggested change it would be only 9.

```svelte
<script lang="ts">
	function multiply(a: number, b: number, ms = Math.random() * 2000) {
	return new Promise((f) => {
		setTimeout(() => f(a * b), ms);
	});
}

	let n = $state(1);
	let y = $state(1);
	let z = $state(1);
</script>

<h1>You can just await things</h1>

<button onclick={() => n += 1}>
	Increment {$state.eager(console.log('a'+n) || n)}
</button>

<button onclick={() => y+=1}>
	{ $state.eager(console.log('b'+y) || y)}
</button>
<button onclick={() => z+=1}>
	{ $state.eager(console.log('c'+z) || z)}
</button>

<p>1 * {n} = {await multiply(n, 1)}</p>
<p>2 * {n} = {await multiply(n, 2)}</p>
<p>3 * {n} = {await multiply(n, 3)}</p>
<p>4 * {n} = {await multiply(n, 4)}</p>
<p>5 * {n} = {await multiply(n, 5)}</p>
```

Code after:
			// the first time this runs, we create an inspect effect
			// that will run eagerly whenever the expression changes
			var previous_batch_values = batch_values;

			try {
				batch_values = null;
				value = fn();
			} finally {
				batch_values = previous_batch_values;
			}

			return;
		}

		// the second time this effect runs, it's to schedule a
		// `version` update. since this will recreate the effect,
		// we don't need to evaluate the expression here
		if (eager_versions.length === 0) {
			queue_micro_task(eager_flush);
		}

		eager_versions.push(version);
	});

	initial = false;

	return value;
}

/**
 * Forcibly remove all current batches, to prevent cross-talk between tests
 */
export function clear() {
	batches.clear();
}