diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js index 67520bc4cc..b8f58395e3 100644 --- a/packages/svelte/src/internal/client/reactivity/deriveds.js +++ b/packages/svelte/src/internal/client/reactivity/deriveds.js @@ -18,7 +18,8 @@ import { update_reaction, increment_write_version, set_active_effect, - component_context + component_context, + handle_error } from '../runtime.js'; import { equals, safe_equals } from './equality.js'; import * as e from '../errors.js'; @@ -83,7 +84,9 @@ export function derived(fn) { */ /*#__NO_SIDE_EFFECTS__*/ export function async_derived(fn) { - if (!active_effect) { + let effect = /** @type {Effect | null} */ (active_effect); + + if (effect === null) { throw new Error('TODO cannot create unowned async derived'); } @@ -91,9 +94,14 @@ export function async_derived(fn) { var value = source(/** @type {V} */ (undefined)); block(() => { - const current = (promise = fn()); + var current = (promise = fn()); + var derived_promise = suspend(promise); + + derived_promise.then((v) => { + if ((effect.f & DESTROYED) !== 0) { + return; + } - suspend(promise).then((v) => { if (promise === current) { internal_set(value, v.exit()); @@ -102,7 +110,9 @@ export function async_derived(fn) { } }); - // TODO what happens when the promise rejects? + derived_promise.catch(e => { + handle_error(e, effect, null, effect.ctx); + }); }, EFFECT_HAS_DERIVED); return promise.then(() => value); diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index b9435b5108..b543208653 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -350,8 +350,14 @@ export function render_effect(fn) { * @param {Array<() => Promise>} async */ export function template_effect(fn, sync = [], async = [], d = derived) { + let effect = /** @type {Effect} */ (active_effect); + if (async.length > 0) { suspend(Promise.all(async.map(async_derived))).then((result) => { + if ((effect.f & DESTROYED) !== 0) { + return; + } + create_template_effect(fn, [...sync.map(d), ...result.exit()]); }); } else { @@ -364,7 +370,7 @@ export function template_effect(fn, sync = [], async = [], d = derived) { * @param {Value[]} deriveds */ function create_template_effect(fn, deriveds) { - const effect = () => fn(...deriveds.map(get)); + var effect = () => fn(...deriveds.map(get)); if (DEV) { define_property(effect, 'name', {