diff --git a/docs/src/content/docs/guides/menus.mdx b/docs/src/content/docs/guides/menus.mdx index 58a9cd313..50023ab4d 100644 --- a/docs/src/content/docs/guides/menus.mdx +++ b/docs/src/content/docs/guides/menus.mdx @@ -366,6 +366,10 @@ You can control when the default context menu appears using the `--default-conte ``` +:::note +This feature will only work as expected after the runtime [has been initialised](../../learn/runtime#initialisation). +::: + #### Nested Context Menu Behavior When using the `--default-contextmenu` property on nested elements, the following rules apply: diff --git a/docs/src/content/docs/learn/bindings.mdx b/docs/src/content/docs/learn/bindings.mdx index 1ca0ee590..d66de725f 100644 --- a/docs/src/content/docs/learn/bindings.mdx +++ b/docs/src/content/docs/learn/bindings.mdx @@ -437,8 +437,9 @@ func (s *MyService) WindowAwareMethod(ctx context.Context) (string, error) { ``` From the frontend, these methods can be called normally. If you need to cancel a -long-running operation, the Promise will be rejected with the cancellation -error: +long-running operation, you can call the special `cancel` method on the promise +and it will reject immediately with a special cancellation error; +the Go context will be cancelled and the actual result of the call will be discarded: ```javascript // Call the method @@ -449,6 +450,84 @@ const promise = MyService.LongRunningTask("input"); promise.cancel(); ``` +In fact, the runtime returns a special promise wrapper +that provides cancellation support for arbitrarily long promise chains. +For example: + +```javascript +import { CancelError } from "@wailsio/runtime"; + +// Call the method and process its output +const promise = MyService.LongRunningTask("input").then((result) => { + console.log(result); +}).catch((err) => { + if (err instanceof CancelError) { + console.log("Cancelled.", err.cause); + } else { + console.error("Failed.", err); + } +}); + +// Later... +// cancel() accepts an optional cause parameter +// that will be attached to the cancellation error: +promise.cancel("I'm tired of waiting!").then(() => { + // Cancellation has been requested successfully + // and all handlers attached above have run. + console.log("Ready for the next adventure!"); +}); +``` + +The `cancel` method returns a promise that fulfills always (and never rejects) +after the cancellation request has been submitted successfully +and all previously attached handlers have run. + +:::note +Calling the `cancel` method on a settled promise is safe and has no effect; +if the task completes before the call to `cancel`, the code above is going to log: + +``` +completed +Ready for the next adventure! +``` + +However, if `cancel` is called before the task finishes, the output will be: + +``` +Cancelled. I'm tired of waiting! +Ready for the next adventure! +``` +::: + +The approach discussed above requires storing and chaining promises manually, +which can be cumbersome for code written in `async`/`await` style. +If you target plaforms that support the `AbortController`/`AbortSignal` idiom, +you can call the `cancelOn` method and tie call cancellation to an `AbortSignal` instead: + +```javascript +async function callBinding(signal) { + try { + await MyService.LongRunningTask("input").cancelOn(signal); + } catch (err) { + if (err instanceof CancelError) { + console.log("Cancelled! Cause: ", err.cause); + } else { + console.error("Failed! Error: ", err); + } + } +} + +let controller = new AbortController(); +callBinding(controller.signal); + +// Later... +controller.abort("I'm tired of waiting!"); +``` + +:::caution +On the macOS platform, `AbortSignal` is only supported from macOS 10.15 Catalina onwards. +::: + ### Handling errors As you may have noticed above, bound methods can return errors, which are handled specially. diff --git a/docs/src/content/docs/learn/context-menu.mdx b/docs/src/content/docs/learn/context-menu.mdx index f56e9a763..ca57f182b 100644 --- a/docs/src/content/docs/learn/context-menu.mdx +++ b/docs/src/content/docs/learn/context-menu.mdx @@ -65,6 +65,10 @@ To associate a context menu with an HTML element, use the `--custom-contextmenu` - `--custom-contextmenu`: Specifies the menu ID (must match the ID used in `NewContextMenu`) - `--custom-contextmenu-data`: Optional data that will be passed to the click handlers +:::note +This feature will only work as expected after the runtime [has been initialised](../runtime#initialisation). +::: + ## Default Context Menu The default context menu is the webview's built-in context menu that provides system-level operations. You can control its visibility using the `--default-contextmenu` CSS property: diff --git a/docs/src/content/docs/learn/runtime.mdx b/docs/src/content/docs/learn/runtime.mdx index 3c2fbfc33..e9780c035 100644 --- a/docs/src/content/docs/learn/runtime.mdx +++ b/docs/src/content/docs/learn/runtime.mdx @@ -22,12 +22,12 @@ The runtime is required for integration between Go and the frontend. There are 2 ways to integrate the runtime: - Using the `@wailsio/runtime` package -- Using a pre-built version of the runtime +- Using a pre-built bundle ## Using the npm package The `@wailsio/runtime` package is a JavaScript package that provides access to -the Wails runtime from the frontend. It is used in by all the standard templates +the Wails runtime from the frontend. It is used by all standard templates and is the recommended way to integrate the runtime into your application. By using the `@wailsio/runtime` package, you will only include the parts of the runtime that you use. @@ -37,25 +37,55 @@ The package is available on npm and can be installed using: npm install --save @wailsio/runtime ``` -## Using a pre-built local version of the runtime +## Using a pre-built bundle Some projects will not use a Javascript bundler and may prefer to use a -pre-built version of the runtime. This is the default for the examples in -`v3/examples`. The pre-built version of the runtime can be generated using the -following command: +pre-built version of the runtime. The pre-built version of the runtime +can be generated using the following command: ```shell wails3 generate runtime ``` This will generate a `runtime.js` (and `runtime.debug.js`) file in the current -directory. This file can be used by your application by adding it to your frontend project: +directory. This file is an ES module that can be imported by your application scripts +just like the npm package, but the API is also exported to the global window object, +so for simpler applications you can use it as follows: ```html - + + - + ``` + +:::caution +It is important to include the `type="module"` attribute on the `