Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Errors now caught when using async events/methods #741

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 25 additions & 0 deletions examples/controllers/async_controller.js
@@ -0,0 +1,25 @@
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
static targets = [ "button" ]

async sleep() {
return new Promise(r => setTimeout(r, 1000));
}


async initialize() {
await this.sleep();
alert('async initialize complete')
}

async run() {
await this.sleep();
alert('Async function complete');
}

async throwError() {
await this.sleep();
throw Error('This error should be caught by stimulus, and stimulus should display a detailed error in the console');
}
}
3 changes: 3 additions & 0 deletions examples/index.js
Expand Up @@ -17,3 +17,6 @@ application.register("slideshow", SlideshowController)

import TabsController from "./controllers/tabs_controller"
application.register("tabs", TabsController)

import AsyncController from "./controllers/async_controller"
application.register("async", AsyncController)
1 change: 1 addition & 0 deletions examples/server.js
Expand Up @@ -23,6 +23,7 @@ const pages = [
{ path: "/slideshow", title: "Slideshow" },
{ path: "/content-loader", title: "Content Loader" },
{ path: "/tabs", title: "Tabs" },
{ path: "/async", title: "Async" },
]

app.get("/", (req, res) => {
Expand Down
13 changes: 13 additions & 0 deletions examples/views/async.ejs
@@ -0,0 +1,13 @@
<%- include("layout/head") %>

<p data-controller="async">
<button data-action="async#run">Click me</button>
</p>

<br />

<p data-controller="async">
<button data-action="async#throwError">Throw error</button>
</p>

<%- include("layout/tail") %>
14 changes: 10 additions & 4 deletions src/core/binding.ts
Expand Up @@ -72,14 +72,20 @@ export class Binding {
}

private invokeWithEvent(event: ActionEvent) {
const handleError = (error: any) => {
const { identifier, controller, element, index } = this
const detail = { identifier, controller, element, index, event }
this.context.handleError(error, `invoking action "${this.action}"`, detail)
}

const { target, currentTarget } = event
try {
this.method.call(this.controller, event)
Promise
.resolve(this.method.call(this.controller, event))
.catch(error => handleError(error))
this.context.logDebugActivity(this.methodName, { event, target, currentTarget, action: this.methodName })
} catch (error: any) {
const { identifier, controller, element, index } = this
const detail = { identifier, controller, element, index, event }
this.context.handleError(error, `invoking action "${this.action}"`, detail)
handleError(error)
}
}

Expand Down
12 changes: 9 additions & 3 deletions src/core/context.ts
Expand Up @@ -30,7 +30,9 @@ export class Context implements ErrorHandler, TargetObserverDelegate, OutletObse
this.outletObserver = new OutletObserver(this, this)

try {
this.controller.initialize()
Promise
.resolve(this.controller.initialize())
.catch(error => this.handleError(error, "initializing controller"))
this.logDebugActivity("initialize")
} catch (error: any) {
this.handleError(error, "initializing controller")
Expand All @@ -44,7 +46,9 @@ export class Context implements ErrorHandler, TargetObserverDelegate, OutletObse
this.outletObserver.start()

try {
this.controller.connect()
Promise
.resolve(this.controller.connect())
.catch(error => this.handleError(error, "connecting controller"))
this.logDebugActivity("connect")
} catch (error: any) {
this.handleError(error, "connecting controller")
Expand All @@ -57,7 +61,9 @@ export class Context implements ErrorHandler, TargetObserverDelegate, OutletObse

disconnect() {
try {
this.controller.disconnect()
Promise
.resolve(this.controller.disconnect())
.catch(error => this.handleError(error, "disconnecting controller"))
this.logDebugActivity("disconnect")
} catch (error: any) {
this.handleError(error, "disconnecting controller")
Expand Down