hybridsjs / hybrids

Extraordinary JavaScript UI framework with unique declarative and functional architecture
https://hybrids.js.org
MIT License
3.05k stars 85 forks source link

The store logs a lot of errors #262

Closed Qsppl closed 1 month ago

Qsppl commented 3 months ago

I throw the required error in the API, like "PaymentRequiredHTTPException".

This error is returned from store.get to be later received by the "store.error()" guard in the component.

const Model = {
    id: true,
    [store.connect]: (id) => {
        const response = api.projects.get(id) // <<< api throw new Payment-Required-HTTP-Exception

        return response.json()
    },
}

In the component I get this error and display a message asking me to pay for the subscription.

const component = define({
    tag: "a-component",
    model: store(Model),
    render: ({ model }) => html`
        ${store.error(model) instanceof PaymentRequiredHTTPException && html`
            <p>You have reached your viewing limit. Please pay for your subscription.</p>
        `}

        ${store.ready(model) && html`
            ...
        `}
    `
})

This all works, but every time this happens, an error is displayed in the console. In some cases, there are more than one hundred thousand errors when opening a page.

This makes it difficult to find real bugs and often breaks dev-tools.

image

Example: https://codepen.io/qsppl/pen/wvLKGWw?editors=1010

smalluban commented 2 months ago

The nature of the store is async and how it "eats" errors (they are attached to the error state of the model, but everything else works) forces it to support passing errors to the console.

If the get method returns a promise, that is rejected, the console error message can be very helpful, as usually people forget to add a rejected path in the UI.

If you have a hundred thousand errors, it means that you fetch that many of the models - it must be an architecture problem with your implementation more than with the library itself ;)

Qsppl commented 2 months ago

I simply display a huge number of interactive objects on the map - roads, points, various economic territories. Everything is fine with this.

The situation is this: api.get()/api.set() during normal application operation often returns errors like HTTPUnauthorizedException/HTTPPaymentRequiredException/HTTPForbiddenException These errors indicate that the user cannot perform some action. These errors do not mean that something is broken in the application. These errors are shown in the console when in fact everything is fine in the application. :( These errors cause false alarms in the error tracker, which prevents us from collecting statistics correctly. :( Previously I intercepted such api-errors with the try { ... } catch { ... } construction and, instead of sending them to stderr, showed in the user interface that the functionality was not available to the user or that the user made an error when filling out the data. Now these errors pop up in stderr and make it difficult to track real errors. :(

If you implement the function of hiding certain classes of errors, the use of errors will become more accessible.

For example, it might look like this:

import { ErrorSuppressionRegister } from "hybrids"
import { HTTPUnauthorizedException, HTTPPaymentRequiredException, HTTPForbiddenException } from "http-exceptions"

ErrorSuppressionRegister.register(HTTPUnauthorizedException)
ErrorSuppressionRegister.register(HTTPPaymentRequiredException)
ErrorSuppressionRegister.register(HTTPForbiddenException)

When a user fills out a form, hybrids throws a lot of errors just to show the user validation messages, so I use crutches to pass the validation error information from the store to the component without “throwing” errors. :(

smalluban commented 1 month ago

I had to think about the problem. With the latest changes in v9 to throw store internal errors early, the need to log errors in the console dropped. Another argument is when a model with an error is used, the access to properties throws, so the usage is still protected.

I moved the router.debug() feature into the global debug() function, which enables that logging. From now, the store won't log errors from [store.connect] method.

hybrids@9.1.3

Qsppl commented 1 month ago

Thank you very much