diff --git a/docs/manual/03 Pointers.md b/docs/manual/03 Pointers.md index 2e30b51d..569a8b82 100644 --- a/docs/manual/03 Pointers.md +++ b/docs/manual/03 Pointers.md @@ -154,7 +154,7 @@ Read more about transform functions in the chapter [Functional Programming](./09 ## Using effects -With transform functions, value can be defined declaratively. +With transform functions, values can be defined declaratively. Still, there are some scenarios where the actual pointer value change event must be handled with custom logic. For this scenario, the `effect()` function can be used. @@ -245,6 +245,32 @@ it is garbage colleted and the effect is removed. Weak value bindings can be used with all *object* values, not just with pointers. +### Async effects + +Effect callbacks cannot be `async` functions. +To handle async operations, you can always call an async function from inside the +effect callback: + +```ts +const searchName = $$(""); +const searchAge = $$(18); + +// async function that searches for a user and shows the result somewhere +async function searchUser(name: string, age: number) { + const user = await query({type: "user", name, age}); + showUser(user); +} + +// effect that triggers the user search every time searchName or searchAge is changed +effect(() => searchUser(searchName.val, searchAge.val)) +``` + +All dependency values of the effect must be accessed synchronously. +This means that the variables inside the async function don't trigger the effect, only the ones passed +into the `searchUser` call. + + + ## Observing pointer changes For more fine grained control, the `observe()` function can be used to handle pointer value updates. diff --git a/runtime/endpoint_config.ts b/runtime/endpoint_config.ts index 03d066ad..cf520c23 100644 --- a/runtime/endpoint_config.ts +++ b/runtime/endpoint_config.ts @@ -94,21 +94,29 @@ class EndpointConfig implements EndpointConfigData { config = await Runtime.executeDatexLocally(serialized, undefined, undefined, globalThis.location?.href ? new URL(globalThis.location.href) : undefined) } // try to get from .dx url - else { - if (!path) path = new URL('/'+this.DX_FILE_NAME, globalThis.location.href) - try { - config = await datex.get(path); + if (!path) path = new URL('/'+this.DX_FILE_NAME, globalThis.location.href) + try { + const configUpdate = await datex.get(path); + if (!config) { + config = configUpdate; logger.info("loaded endpoint config from " + path); } - catch (e) { - // ignore if no .dx file found - if (!(await fetch(path)).ok) {} - else { - logger.error `Could not read config file ${path}: ${e.toString()}`; - throw "invalid config file" + else { + for (const [key, value] of DatexObject.entries(configUpdate as Record)) { + DatexObject.set(config as Record, key as string, value); } + logger.debug("updated endpoint config from " + path); + } + } + catch (e) { + // ignore if no .dx file found + if (!(await fetch(path)).ok) {} + else { + logger.error `Could not read config file ${path}: ${e.toString()}`; + throw "invalid config file" } } + } else { logger.debug("Cannot load endpoint config file for client type '" + client_type + "'")