raptor-render-context
Advanced tools
Comparing version 0.2.15-beta to 0.2.16-beta
@@ -62,24 +62,2 @@ /* | ||
function getAsyncAttributes(context) { | ||
var attrs = context.attributes; | ||
return attrs.async; | ||
} | ||
function handleEnd(context, asyncAttributes) { | ||
if (!asyncAttributes.lastFired) { | ||
context.emit('last'); | ||
asyncAttributes.last = 0; | ||
asyncAttributes.lastFired = true; | ||
} | ||
if (asyncAttributes.remaining === 0) { | ||
// If we were the last fragment to complete then fulfil the promise for | ||
// the template rendering using the output of the underlying writer | ||
context.emit('end'); | ||
} | ||
} | ||
function Fragment(context) { | ||
@@ -122,36 +100,19 @@ this.context = context; | ||
}; | ||
function AsyncFragment(context) { | ||
Fragment.call(this, context); | ||
this.timeoutId = null; | ||
} | ||
AsyncFragment.prototype = { | ||
end: function (e) { | ||
if (this.timeoutId) { | ||
clearTimeout(this.timeoutId); | ||
} | ||
end: function () { | ||
if (!this.finished) { | ||
// Make sure end is only called once by the user | ||
this.finished = true; | ||
try { | ||
if (e) { | ||
logger.error('Async fragment failed. Exception: ' + (e.stack || e) + (this.stack ? ('\nCreation stack trace: ' + this.stack) : '')); | ||
this.context.emit('error', e); | ||
} | ||
} finally { | ||
if (!this.finished) { | ||
// Make sure end is only called once by the user | ||
this.finished = true; | ||
var asyncAttributes = getAsyncAttributes(this.context); | ||
if (this.ready) { | ||
// There are no nested asynchronous fragments that are | ||
// remaining and we are ready to be flushed then let's do it! | ||
this.flush(); | ||
} | ||
// Keep track of how many asynchronous fragments are in the template | ||
// NOTE: firstPassComplete changes to true after processing all of the nodes of the template | ||
if (--asyncAttributes.remaining - asyncAttributes.last === 0 && asyncAttributes.ended) { | ||
handleEnd(this.context, asyncAttributes); | ||
} | ||
if (this.ready) { | ||
// There are no nested asynchronous fragments that are | ||
// remaining and we are ready to be flushed then let's do it! | ||
this.flush(); | ||
} | ||
@@ -169,9 +130,2 @@ } | ||
flushNext(this, writer); | ||
}, | ||
addTimeoutHandler: function(timeoutMillis) { | ||
var _this = this; | ||
this.timeoutId = setTimeout(function () { | ||
_this.end('Async fragment timed out after ' + timeoutMillis + 'ms.'); | ||
}, timeoutMillis); | ||
} | ||
@@ -200,3 +154,4 @@ }; | ||
ended: false, | ||
last: 0 | ||
last: 0, | ||
lastFlushSupported: this.lastFlushSupported !== false | ||
}; | ||
@@ -250,5 +205,4 @@ } | ||
beginAsync: function (options) { | ||
var asyncAttributes = getAsyncAttributes(this); | ||
// Keep a count of all of the async fragments for this rendering | ||
asyncAttributes.remaining++; | ||
@@ -284,6 +238,17 @@ var ready = true; | ||
// Record the previous async fragment for linking purposes | ||
asyncFragment.stack = includeStack ? new Error().stack : null; | ||
asyncContext.handleBeginAsync(options); | ||
return asyncContext; | ||
}, | ||
handleBeginAsync: function(options) { | ||
var async = this.attributes.async; | ||
var timeout; | ||
async.remaining++; | ||
if (options != null) { | ||
@@ -295,7 +260,7 @@ if (typeof options === 'number') { | ||
if (options.last === true) { | ||
asyncAttributes.last++; | ||
async.last++; | ||
} | ||
} | ||
} | ||
if (timeout == null) { | ||
@@ -305,7 +270,11 @@ timeout = Context.DEFAULT_TIMEOUT; | ||
var _this = this; | ||
_this.stack = includeStack ? new Error().stack : null; | ||
if (timeout > 0) { | ||
asyncFragment.addTimeoutHandler(timeout); | ||
_this._timeoutId = setTimeout(function() { | ||
_this.error(new Error('Async fragment timed out after ' + timeout + 'ms')); | ||
}, timeout); | ||
} | ||
return asyncContext; | ||
}, | ||
@@ -338,6 +307,8 @@ on: function(event, callback) { | ||
error: function(e) { | ||
if (this._af) { | ||
this._af.end(e); | ||
} else { | ||
this.emit('error', e); | ||
try { | ||
var stack = this.stack; | ||
logger.error('Async fragment failed. Exception: ' + (e.stack || e) + (stack ? ('\nCreation stack trace: ' + stack) : '')); | ||
this.emit('error', e); | ||
} finally { | ||
this.end(); | ||
} | ||
@@ -351,14 +322,49 @@ }, | ||
if (this._af) { | ||
this._af.end(); | ||
var asyncFragment = this._af; | ||
if (asyncFragment) { | ||
asyncFragment.end(); | ||
this.handleEnd(true); | ||
} else { | ||
var async = this.attributes.async; | ||
this.handleEnd(false); | ||
} | ||
return this; | ||
}, | ||
handleEnd: function(isAsync) { | ||
var async = this.attributes.async; | ||
var isCompleted = false; | ||
// Keep track of how many asynchronous fragments are in the template | ||
// NOTE: firstPassComplete changes to true after processing all of the nodes of the template | ||
if (isAsync) { | ||
var timeoutId = this._timeoutId; | ||
if (timeoutId) { | ||
clearTimeout(timeoutId); | ||
} | ||
if (--async.remaining - async.last === 0 && async.ended) { | ||
isCompleted = true; | ||
} | ||
} else { | ||
async.ended = true; | ||
if (async.remaining - async.last === 0) { | ||
handleEnd(this, async); | ||
isCompleted = true; | ||
} | ||
} | ||
return this; | ||
if (isCompleted) { | ||
if (!async.lastFired) { | ||
this.emit('last'); | ||
async.last = 0; | ||
async.lastFired = true; | ||
} | ||
if (async.remaining === 0) { | ||
this.emit('end'); | ||
} | ||
} | ||
} | ||
@@ -365,0 +371,0 @@ }; |
@@ -29,3 +29,3 @@ { | ||
}, | ||
"version": "0.2.15-beta" | ||
"version": "0.2.16-beta" | ||
} |
@@ -299,3 +299,3 @@ 'use strict'; | ||
it.only('should support a render context being piped to another stream', function(done) { | ||
it('should support a render context being piped to another stream', function(done) { | ||
@@ -302,0 +302,0 @@ var through = require('through')(); |
28086
649