Last active
August 29, 2015 14:27
-
-
Save cmmartin/82b32308358b13ecf483 to your computer and use it in GitHub Desktop.
Streaming server middleware
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import koa from 'koa' | |
import router from 'koa-route' | |
import streamView from './stream-view' | |
const app = koa() | |
const toJS = str => JSON.parse(str) | |
const toJSON = js => JSON.stringify(js) | |
// stream an html page with asynchronous data | |
app.use(router.get('/html/:title', streamView('html', function* (title) { | |
yield ` | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>${ title }</title> | |
<meta charset="utf-8"> | |
<link rel="stylesheet" href="/bundle.css?${this.request.querystring}" /> | |
</head> | |
<body> | |
<div class="mount-node"></div> | |
<script type="text/javascript"> | |
window.props = `; yield getProps(this.request.query); yield `; | |
</script> | |
<script type="text/javascript" src="bundle.js"></script> | |
</body> | |
</html> | |
` | |
}))) | |
// stream a json file | |
// potentially useful for condensing many requests into one | |
app.use(router.get('/all-the-things.json', streamView('json', function* (title) { | |
yield getProps(this.request.query) | |
}))) | |
function *getProps(queryParams) { | |
return toJSON({ | |
foo: yield fetch(`/some/api`).then(toJS), | |
bar: yield fetch(`/some/api/${queryParams.thing}`).then(toJS), | |
baz: yield fetch(`/some/api/${queryParams.anotherThing}`).then(toJS) | |
}) | |
} | |
app.listen(3000) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import StreamView from './stream-view' | |
export default function getMiddleware(type, chunkGenerator) { | |
return function *(options) { | |
this.type = type | |
this.body = new StreamView(this, chunkGenerator.bind(this), options) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Readable } from 'stream' | |
import co from 'koa/node_modules/co' | |
export default StreamView | |
// TODO: allow the chunkGenerator to yield objects as well as strings (JSON.stringify them) | |
class StreamView extends Readable { | |
constructor(context, chunkGenerator, options) { | |
super({}) | |
this.chunkGenerator = chunkGenerator | |
co.call(this, this.render.bind(this, options)).catch(context.onerror) | |
} | |
*render(options) { | |
for (let chunk of this.chunkGenerator.call(this, options)) { | |
this.push(typeof chunk === 'string' ? chunk : yield* chunk) | |
} | |
this.push(null) // end the stream | |
} | |
_read() {} // override | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment