Skip to content

Commit a1e03b2

Browse files
authored
Merge pull request #20 from costrojs/feat/async-render
Enable asynchronous on beforeRender method
2 parents d136f2b + 0f7938d commit a1e03b2

File tree

5 files changed

+255
-48
lines changed

5 files changed

+255
-48
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# CHANGELOG
22

3+
## 2.2.0
4+
5+
### New features
6+
7+
- Add asynchronous `beforeRender` hook ([#20](https://github.com/costrojs/costro/pull/20))
8+
39
## 2.1.2
410

511
### Fixes

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "costro",
3-
"version": "2.1.2",
3+
"version": "2.2.0",
44
"description": "Build web applications with Components, Store and Router in 3KB",
55
"keywords": [
66
"costro",

src/app.ts

+48-17
Original file line numberDiff line numberDiff line change
@@ -256,19 +256,26 @@ export default class App {
256256
this.initComponentInCache()
257257
}
258258

259-
let componentView = this.getComponentView()
260-
if (componentView) {
261-
if (!this.currentRoute.interfaceType) {
262-
this.currentRoute.interfaceType = this.getInterfaceTypeFromView(componentView)
263-
this.routes.set(this.currentRoute.path, this.currentRoute)
264-
}
259+
this.getComponentView()
260+
.then((componentView) => {
261+
if (componentView && this.currentRoute) {
262+
if (!this.currentRoute.interfaceType) {
263+
this.currentRoute.interfaceType =
264+
this.getInterfaceTypeFromView(componentView)
265+
this.routes.set(this.currentRoute.path, this.currentRoute)
266+
}
265267

266-
if (this.currentRoute.interfaceType === 'STRING') {
267-
componentView = this.transformLinksInStringComponent(componentView)
268-
}
269-
this.target.appendChild(componentView)
270-
this.currentRoute.isComponentClass && this.currentRoute.component.afterRender()
271-
}
268+
if (this.currentRoute.interfaceType === 'STRING') {
269+
componentView = this.transformLinksInStringComponent(componentView)
270+
}
271+
this.target.appendChild(componentView)
272+
this.currentRoute.isComponentClass &&
273+
this.currentRoute.component.afterRender()
274+
}
275+
})
276+
.catch((error) => {
277+
console.warn('getComponentView::promise rejected', error)
278+
})
272279
}
273280
}
274281

@@ -305,15 +312,39 @@ export default class App {
305312
if (this.currentRoute) {
306313
if (this.currentRoute.isComponentClass) {
307314
this.updateComponentRouteData()
308-
this.currentRoute.component.beforeRender()
309-
return this.currentRoute.component.render()
310-
} else {
311-
return this.currentRoute.component.call(
315+
const beforeRenderFn = this.currentRoute.component.beforeRender()
316+
317+
if (beforeRenderFn instanceof Promise) {
318+
return this.runRenderWhenReady(this.currentRoute, beforeRenderFn)
319+
}
320+
321+
return Promise.resolve(this.currentRoute.component.render())
322+
}
323+
324+
return Promise.resolve(
325+
this.currentRoute.component.call(
312326
this.currentRoute.component,
313327
this.currentRoute.props
314328
)
315-
}
329+
)
316330
}
331+
332+
return Promise.reject(new Error('getComponentView::promise not resolved'))
333+
}
334+
335+
/**
336+
* Run render function when asynchronous before render is resolved
337+
* @param currentRoute Current route
338+
* @param beforeRenderFn Before render promise
339+
* @returns The render content
340+
*/
341+
runRenderWhenReady(currentRoute: RouteData, beforeRenderFn: Promise<unknown>) {
342+
return Promise.resolve(beforeRenderFn).then(() => {
343+
// Check is route has changed before the promise resolution
344+
if (this.currentRoute && this.currentRoute.path === currentRoute.path) {
345+
return currentRoute.component.render()
346+
}
347+
})
317348
}
318349

319350
/**

0 commit comments

Comments
 (0)