Skip to content

Commit

Permalink
Merge pull request #20 from costrojs/feat/async-render
Browse files Browse the repository at this point in the history
Enable asynchronous on beforeRender method
  • Loading branch information
yoriiis authored Sep 26, 2024
2 parents d136f2b + 0f7938d commit a1e03b2
Show file tree
Hide file tree
Showing 5 changed files with 255 additions and 48 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# CHANGELOG

## 2.2.0

### New features

- Add asynchronous `beforeRender` hook ([#20](https://github.com/costrojs/costro/pull/20))

## 2.1.2

### Fixes
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "costro",
"version": "2.1.2",
"version": "2.2.0",
"description": "Build web applications with Components, Store and Router in 3KB",
"keywords": [
"costro",
Expand Down
65 changes: 48 additions & 17 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,19 +256,26 @@ export default class App {
this.initComponentInCache()
}

let componentView = this.getComponentView()
if (componentView) {
if (!this.currentRoute.interfaceType) {
this.currentRoute.interfaceType = this.getInterfaceTypeFromView(componentView)
this.routes.set(this.currentRoute.path, this.currentRoute)
}
this.getComponentView()
.then((componentView) => {
if (componentView && this.currentRoute) {
if (!this.currentRoute.interfaceType) {
this.currentRoute.interfaceType =
this.getInterfaceTypeFromView(componentView)
this.routes.set(this.currentRoute.path, this.currentRoute)
}

if (this.currentRoute.interfaceType === 'STRING') {
componentView = this.transformLinksInStringComponent(componentView)
}
this.target.appendChild(componentView)
this.currentRoute.isComponentClass && this.currentRoute.component.afterRender()
}
if (this.currentRoute.interfaceType === 'STRING') {
componentView = this.transformLinksInStringComponent(componentView)
}
this.target.appendChild(componentView)
this.currentRoute.isComponentClass &&
this.currentRoute.component.afterRender()
}
})
.catch((error) => {
console.warn('getComponentView::promise rejected', error)
})
}
}

Expand Down Expand Up @@ -305,15 +312,39 @@ export default class App {
if (this.currentRoute) {
if (this.currentRoute.isComponentClass) {
this.updateComponentRouteData()
this.currentRoute.component.beforeRender()
return this.currentRoute.component.render()
} else {
return this.currentRoute.component.call(
const beforeRenderFn = this.currentRoute.component.beforeRender()

if (beforeRenderFn instanceof Promise) {
return this.runRenderWhenReady(this.currentRoute, beforeRenderFn)
}

return Promise.resolve(this.currentRoute.component.render())
}

return Promise.resolve(
this.currentRoute.component.call(
this.currentRoute.component,
this.currentRoute.props
)
}
)
}

return Promise.reject(new Error('getComponentView::promise not resolved'))
}

/**
* Run render function when asynchronous before render is resolved
* @param currentRoute Current route
* @param beforeRenderFn Before render promise
* @returns The render content
*/
runRenderWhenReady(currentRoute: RouteData, beforeRenderFn: Promise<unknown>) {
return Promise.resolve(beforeRenderFn).then(() => {
// Check is route has changed before the promise resolution
if (this.currentRoute && this.currentRoute.path === currentRoute.path) {
return currentRoute.component.render()
}
})
}

/**
Expand Down
Loading

0 comments on commit a1e03b2

Please sign in to comment.