Open
Description
Hi,
Really liking Choo so far! One thing I was missing was the ability to define an async route (I'm working on a game and wanted to preload assets). I didn't see a simple way to accomplish this (maybe I missed something obvious), so I wrote a little module that augments app with an asyncRoute
method:
const app = withAsyncRoute(choo());
app.asyncRoute('/', loadResources,
() => html`<div id="root"><h1>Loading...</h1></div>`,
(state, emit, data) => html`<div id="root">Loaded ${data}</div>`
(state, emit, err, params) => {
console.error('error loading /:', params, err, state);
return html`
<div id="root">
<h1 style="color: red">Error loading / (see console)</h1>
</div>
`;
},
);
Was wondering if there's interest in either merging this function into Choo proper, or as a third-party npm module?
For reference, here's the module -- it's pretty simple:
module.exports = (app) => Object.assign(app, {
/**
* @param {string} route
* @param {Promise<Data>|Function<Promise<Data>>} promise
* @param {Function<State, Emitter, RouteParams>} loadingHandler
* @param {Function<State, Emitter, Data, RouteParams>} loadedHandler
* @param {Function<State, Emitter, *, RouteParams>} errorHandler
*/
asyncRoute: (route, promise, loadingHandler, loadedHandler, errorHandler) => {
app.use((state, emitter) => {
const emit = emitter.emit.bind(emitter);
app.router.on(route, (params) => {
state.params = params;
if (typeof promise === 'function') {
promise = promise();
}
let completed = false;
let isError = false;
let data = null;
promise.then(result => {
completed = true;
data = result;
emitter.emit('render');
}).catch(err => {
completed = isError = true;
data = err;
emitter.emit('render');
});
return () => {
if (!completed) {
return loadingHandler(state, emit, params);
} else if (isError) {
return errorHandler(state, emit, data, params);
} else {
return loadedHandler(state, emit, data, params);
}
};
});
});
}
});
Metadata
Metadata
Assignees
Labels
No labels