I've not used the proxy() method before but one way I got around this problem was to keep deferreds out of render() and only call render() inside of the done() callback of the deferred.
That just shifts the point of failure to the asynchronous retrieval of the EJS view. For a solid solution you
must
check in one way or another if the control has been disposed of or not when the callback is called.
The quickest way to do that is indeed to simply check for
this.element
inside the callback. A more involved, but possibly more reusable way is to provide a member method on a control that wraps the
can.view
call to add this check around the callback parameter. It's also a bit more inviting to modifying the returned
can.Deferred
object to be morphed into a rejected state as well, as said code can be a bit more involved:
view : function( view, data, helpers, fn ) {
var
me = this,
result;
result = can
.view( view, data, helpers, function() { return me.element ? fn.apply(this, arguments ) : undefined })
.pipe( function( val ) { return me.element ? val : can.Deferred.reject() });
return result;
}