Currently rendering a template returns an AsyncWriter, it would be handy though if when a callback is omitted that templates render function returned a promise.
var template = require("template.marko");
template.render({ hello: "world" })
.then(function (html) { ... })
.catch(function (err) { ... });
If you're using promises already it makes using marko a bit easier.
You can use temporarily bluebird module.
let Promise = require('bluebird');
let EntryCommentsMarkup = require('./views/EntryComments.marko');
Promise.promisifyAll(EntryCommentsMarkup);
then in routing we invoke renderAsync method:
app.get('/example', function(req, res) {
let Data = { ... };
return EntryCommentsMarkup.renderAsync(Data)
.then((markup) => res.status(200).json({ markup: markup }))
.catch((error) => res.status(400).json({ message: error.message }));
});
/CC @philidem @mlrawlings
I would like to see a method that returns a promise, but I would prefer to avoid a breaking change. The purpose of returning the AsyncWriter instance was to be compatible with the EventEmitter API (on, once, emit, etc.) that AsyncWriter implements. For example:
template.render({ hello: "world" })
.on('foo', function(e) {
})
.on('error', function(e) {
})
.on('finish', function() {
})
What are your all thoughts on utilizing the native promise implementation to provide a new renderAsync method?:
var template = require("template.marko");
template.renderAsync({ hello: "world" })
.then(function (html) { ... })
.catch(function (err) { ... });
I'd rather modify async-writer to be a thenable by adding .then and .catch
I've seen other libraries such as superagent and mongoose implement a promise-like interface that plays well with anything that is duck-typing rather than looking at instanceof Promise (which is most everything due to things like bluebird and q).
It would support both
template.render({ hello:"world" })
.then(function (html) { ... })
.catch(function (err) { ... });
and
template.render({ hello:"world" })
.on('error', function(e) { ... })
.on('finish', function() { ... })
And with async/await you'd be able to do:
var html = await template.render({ hello:"world" })
We could also implement a .promise function (or some other name) that returns a true Promise for cases where it is needed.
Expand for possible implementation
{
then(fn, fnErr) {
var promise = new Promise((resolve, reject) => {
var buffer = ''
this.on('data', data => buffer += data)
this.on('error', error => reject(error))
this.on('finish', () => {
try {
resolve(fn(buffer))
} catch(err) {
reject(err)
}
})
})
if(fnErr) {
promise = promise.catch(fnErr)
}
return promise
}
promise() {
return this.then(x => x)
}
catch(fn) {
return this.promise().catch(fn)
}
}
I like the suggestion to implement the then and catch methods on the AsyncWriter instance. Let's go forward with that approach.
FYI: it should be sufficient to add the then() and catch() methods to OutMixins.js since those mixins are added to both AsyncStream and AsyncVDOMBuilder
NOTE: We want to follow the rules for having a consistent rendering API: https://github.com/marko-js/marko/issues/389
That is:
template.render({})
.then(function(out) {
out.appendTo(document.body);
});
A bit late, just throwing this out there: The Promises/A+ specification requires that if the result is an object or function with a then method, it _must_ be treated as a "thenable". In other words, this solution is explicitly permitted by the specification, and any Promise library which doesn't handle this correctly is - by definition - "broken". That's all, carry on. :)
Most helpful comment
I'd rather modify
async-writerto be a thenable by adding.thenand.catchI've seen other libraries such as
superagentandmongooseimplement a promise-like interface that plays well with anything that is duck-typing rather than looking atinstanceof Promise(which is most everything due to things likebluebirdandq).It would support both
and
And with async/await you'd be able to do:
We could also implement a
.promisefunction (or some other name) that returns a truePromisefor cases where it is needed.Expand for possible implementation