mirror of https://github.com/sveltejs/svelte
parent
591aeb0cbc
commit
7144f11b5b
@ -1,37 +1,24 @@
|
||||
/** @import { Effect, TemplateNode, Value } from '#client' */
|
||||
import { DESTROYED } from '#client/constants';
|
||||
import { async_derived } from '../../reactivity/deriveds.js';
|
||||
import { active_effect, get } from '../../runtime.js';
|
||||
import { capture, get_pending_boundary } from './boundary.js';
|
||||
/** @import { TemplateNode, Value } from '#client' */
|
||||
import { flatten } from '../../reactivity/async.js';
|
||||
import { get } from '../../runtime.js';
|
||||
import { get_pending_boundary } from './boundary.js';
|
||||
|
||||
/**
|
||||
* @param {TemplateNode} node
|
||||
* @param {Array<() => Promise<any>>} expressions
|
||||
* @param {(anchor: TemplateNode, ...deriveds: Value[]) => void} fn
|
||||
*/
|
||||
export async function async(node, expressions, fn) {
|
||||
// TODO handle hydration
|
||||
|
||||
var parent = /** @type {Effect} */ (active_effect);
|
||||
|
||||
var restore = capture();
|
||||
export function async(node, expressions, fn) {
|
||||
var boundary = get_pending_boundary();
|
||||
|
||||
// TODO why is this necessary? doesn't it happen inside `async_derived` inside `flatten`?
|
||||
boundary.update_pending_count(1);
|
||||
|
||||
try {
|
||||
const deriveds = await Promise.all(expressions.map((fn) => async_derived(fn)));
|
||||
|
||||
// get deriveds eagerly to avoid creating blocks if they reject
|
||||
for (const d of deriveds) get(d);
|
||||
flatten([], expressions, (values) => {
|
||||
// get values eagerly to avoid creating blocks if they reject
|
||||
for (const d of values) get(d);
|
||||
|
||||
if ((parent.f & DESTROYED) !== 0) return;
|
||||
|
||||
restore();
|
||||
fn(node, ...deriveds);
|
||||
} catch (error) {
|
||||
boundary.error(error);
|
||||
} finally {
|
||||
fn(node, ...values);
|
||||
boundary.update_pending_count(-1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
/** @import { Effect, Value } from '#client' */
|
||||
|
||||
import { DESTROYED } from '#client/constants';
|
||||
import { is_runes } from '../context.js';
|
||||
import { capture, get_pending_boundary } from '../dom/blocks/boundary.js';
|
||||
import { invoke_error_boundary } from '../error-handling.js';
|
||||
import { active_effect } from '../runtime.js';
|
||||
import { current_batch } from './batch.js';
|
||||
import { async_derived, derived, derived_safe_equal } from './deriveds.js';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Array<() => any>} sync
|
||||
* @param {Array<() => Promise<any>>} async
|
||||
* @param {(values: Value[]) => any} fn
|
||||
*/
|
||||
export function flatten(sync, async, fn) {
|
||||
const d = is_runes() ? derived : derived_safe_equal;
|
||||
|
||||
if (async.length > 0) {
|
||||
var batch = current_batch;
|
||||
var parent = /** @type {Effect} */ (active_effect);
|
||||
|
||||
var restore = capture();
|
||||
|
||||
var boundary = get_pending_boundary();
|
||||
|
||||
Promise.all(async.map((expression) => async_derived(expression)))
|
||||
.then((result) => {
|
||||
if ((parent.f & DESTROYED) !== 0) return;
|
||||
|
||||
batch?.restore();
|
||||
|
||||
restore();
|
||||
|
||||
try {
|
||||
fn([...sync.map(d), ...result]);
|
||||
} catch (error) {
|
||||
invoke_error_boundary(error, parent);
|
||||
}
|
||||
|
||||
batch?.flush();
|
||||
})
|
||||
.catch((error) => {
|
||||
boundary.error(error);
|
||||
});
|
||||
} else {
|
||||
fn(sync.map(d));
|
||||
}
|
||||
}
|
Loading…
Reference in new issue