Using Extjs 4.1, an intermittent error is occurring.
Sometimes it occurs, but most of the time it does not.
It always occurs when I start the application, so I press F5 and everything returns to normal.
Using this reference to debug the error, I noticed that it occurs at line 29590.
The error message is very generic:
Uncaught TypeError: Cannot read property 'dom' of null
at constructor.finishRender (ext-all-debug-w-comments.js:29590)
at constructor.finishRenderItems (ext-all-debug-w-comments.js:39796)
at constructor.finishRender (ext-all-debug-w-comments.js:40889)
at constructor.finishRenderChildren (ext-all-debug-w-comments.js:44526)
at constructor.afterRender (ext-all-debug-w-comments.js:29331)
at constructor.callParent (ext-all-debug-w-comments.js:6194)
at constructor.afterRender (ext-all-debug-w-comments.js:36521)
at constructor.finishRender (ext-all-debug-w-comments.js:29625)
at constructor.finishRenderItems (ext-all-debug-w-comments.js:39796)
at constructor.finishRender (ext-all-debug-w-comments.js:40889)
Here is an error print
What must be causing this?
I would have made this a comment, but it doesn't fit.
There is a wide variety of reasons I could think of. Most of them are based on asynchronous calls. You definitely have to provide more information for the question to be answerable.
Obviously, me.el is null, which it shouldn't be. So first you have to find which component is causing the problem. For this, you should exchange line 29590 against something like this:
try {
me.container = Ext.get(me.el.dom.parentNode);
} catch(e) {
console.log(me.id);
console.log(me.itemId);
console.log(me.xtype);
...
console.log(me);
throw e;
}
This should give you an idea which component(s) would be affected.
Then show us the code of that component. Also check whether you modify that component's config from outside the component, e.g. from a store load operation or other asynchronous tasks. Plus you should look at whether overrides for the component and its ancestors are loaded from separate JS files - maybe they are sometimes loaded before, sometimes after the finishRender has been called, and fix exactly this error.
These are only a few of the possible reasons.
Related
How can I solve this error:
core.js:1449 ERROR Error: Uncaught (in promise): TypeError: Cannot
read property 'slug' of undefined TypeError: Cannot read property
'slug' of undefined
My code:
this.WooCommerce.getAsync("products?filter[category]=" + this.category.slug).then((data) =>{
console.log(JSON.parse(data.body));
well to me this confirms what I first said. you are indeed pointing to a child of an object within an observable (whether you know what observables are or not) (observables sometimes move all the way up the priority list and happen before hydration of any other var).
so here's the precautions I like to take to make sure things don't go badly: splitting things up.
Also, here's a "hack" I like to use on a general basis in order to ensure I can continue my dev cycle unhindered and have a better notion of where things are failing other than just "undefined":
this.category['slug'];
I never go this far but this is also allowed :
this['category']['slug'];
see this is different because it will actually return the undefined instead of failing there at a JS level.
now to me it seems pretty obvious that you need to ascertain this.category.slug in the instant it's being evaluated isn't in a state in it's lifeline prior to it's initialization :
var myFunctionToLogSlug = () => { //here you could pass this.category.slug as an arg but
//that's the same as simply calling in within the body of this method because your
//context (this) is the same, ergo the pointer and timeframe are also the same.
console.log("is this.category.slug empty ? : ", this.category.slug);
return this.category.slug;
};
this.WooCommerce.getAsync(
"products?filter[category]=" + myFunctionToLogSlug()).then(data =>{
console.log(JSON.parse(data.body));
});
once you've ascertained this.category.slug is indeed undefined at the point it is called, you can either move this.WooCommerce.getAsync to a time-place you know this.category.slug to be defined, or move this.category.slug's hydration to the inside of the getAsync.
hope this helps ! :)
I have a classic asp project. In one of my pages i have to call a javascript function. That call does not have any problem and works fine on my test server (not localhost, just a server to test he project). But when i deploy it to the actual server, that function does not work. I call this function in onload event.
That function has this type of lines (i cannot write the whole code, because of the company that i work for, does not allow it)
document.getElementById("R6C2_1").style.display = 'block'
document.getElementById("R6C2_2").style.display = 'none'
....
When I try to debug it on IE10, i got "Unable to get property 'style' of undefined or null reference" error. After that, the elements in javascript function are not load. They are not seen on the page.
My main problem is, as i mentioned before differences between servers. I do not understand why it works on one server, but not on another server.
While it's not possible to determine the issue from this information alone, you should look into:
Whether the elements you're looking for actually exist when the code is invoked (use browser debug / breakpoints to look at the page the moment the code is invoked).
If they exist, check if they have the ID you expect (e.g R6C2_1) - if not, why? who creates these IDs? could be a server configuration issue.
Do a debug using the app from each server, and look at the page / DOM, see if there are differences or check if the code is invoked at different times.
These could lead you to pinpoint the issue. Good luck!
In case the elements just take time to be created, you can just wait until they are present:
function ExecuteWhenExists() {
var R6C2_1 = document.getElementById("R6C2_1");
var R6C2_2 = document.getElementById("R6C2_2");
if (R6C2_1 && R6C2_2) {
R6C2_1.style.display = 'block';
R6C2_2.style.display = 'none';
} else {
window.setTimeout(ExecuteWhenExists, 100);
}
}
ExecuteWhenExists();
This will not crash when the elements do not exist, and will just keep trying to execute in a non-blocking way (polling every 0.1 seconds) until they exist.
I'm getting an exception from one of my template helpers in Meteor - even though I see my logs just fine.
Template.DashboardHeader.helpers({
avatar: function () {
if (Meteor.user().profile.image){
console.log('yea');
} else {
console.log('nah');
}
}
})
I'll eventually be using it to serve an avatar, depending on whether or not the user has set one in their account. The helper actually works as you might expect and logs the correct output depending on the situation, but I get this big unhelpful exception whenever it's run:
Exception in template helper: .avatar#http://localhost:3000/client/master.js?86599d1d506dfe7d57211f3faa8757db9ba5cb81:16:9
BlazeProvider.helpers/http://localhost:3000/packages/meteorhacks_kadira-debug.js?ee5ca93234e8f5b94a8e5560eb5ea8b7fcbb9c4d:339:26
... a lot more lines later...
Tracker._runFlush#http://localhost:3000/packages/tracker.js?6d0890939291d9780f7e2607ee3af3e7f98a3d9c:485:9
onGlobalMessage#http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:372:11
Given that it doesn't really tell me anything (that I can see/understand) I'm not sure what to be troubleshooting!
Here's the template code (simplified):
<template name="DashboardHeader">
<img id="user-img" src="{{ avatar }}" alt="{{ currentUser.profile.name }}" width="34px" height="34px" />
</template>
Although the exception triggers wherever the {{ avatar }} is placed within the template tags. But doesn't trigger if it's not present in the template. So it seems it's got less to do with the helper itself than how it's being applied.
Anyone knows what's up with it?
This kind of error (huge exception in console but data appears in template) is generally due to a reactive dependency being undefined and queried upon.
Take the following example:
Template.myTemplate.helpers({
'name' : () => MyCollection.findOne().name
})
Depending on data availability or the subscription strategy the above can throw an exception because MyCollection.findOne() is undefined when first called.
However the correct output will still appear once the data is available (subscription kicked in). findOne invalidates its dependencies (including the helper) and because the name is now present it will show in the template.
In your case it means either Meteor.user() or Meteor.user().profile is undefined when first called.
To solve easily you can use some short-circuiting :
//Will return undefined if findOne() is undefined
() => (MyCollection.findOne() && MyCollection.findOne().name)
There is other ways to implement such undefined checks of course.
You also seem to be using Firefox.
Meteor spews out hideous stack traces with no error reasons on some browsers.
On Chrome, this is what such an error looks like with my example :
Exception in template helper: TypeError: Cannot read property 'name' of undefined
at (... stacktrace ...)
So when you see giant unintelligible String-joined stacktraces, check if you can have more useful information on another browser.
I have built a complete demo of this behaviour on MeteorPad.
If you've ever worked with ExtJs, you've probably run into the nefarious "Cannot read property 'dom' of null" exception. For me, it usually happens inside doInsert (the last of 14 stacks in the outer trace) (ExtJs's code):
doInsert: function(el, o, returnElement, pos, sibling, append) {
//<My own comment>: hint: el === null (curiously not undefined?)
el = el.dom || Ext.getDom(el);
var newNode;
...
}
This happens when you attempt to attach an ExtJs component (Tree, Grid, Button, whatever) to a DOM element which is not yet in the DOM. Usually the element is in memory, constructed as part of an AJAX request, ready to be inserted on success.
The problem is that when ExtJS throws, it fundamentally breaks every ExtJs component in the page. All grids, trees, menus, buttons are immediately mangled. Event bindings like click and hover either do nothing or generate exceptions.
I currently mitigate against this by first doing a document.getElementById check, and if the result is undefined, then I defer 100 ms and try again. This is ugly, but it works. It's also expensive to do. As certain pages get more complex, that's more and more document.getElementById defer loops; and it gets harder and harder to track down which method inside which module hasn't tested getElementById.
It's a mess.
Question: is there any way to force ExtJS to throw gracefully? To override its exception handling mechanism? Flip the "dontBreakTheEntirePage" configuration variable?
UPDATE:
After trying to go direct to Sencha and after a few rebuffs, I demonstrated the problem more clearly (I hope):
EDIT: Sencha is moderating my replies to the original thread. If you have any interest in this class of fault, please add to the discussion.
Open the docs (http://docs.sencha.com/extjs/4.1.0/)
Open a few tabs (I have Ext, Ext.tree.Panel, Ext.menu.Menu, Ext.AbstractComponent, and Ext.draw.Color)
Open the Chrome Dev Tools and look for errors.
Click back and forth between tabs a few times as a sanity check. Tabs render as expected, without error.
Now, let's break the page.
Back to the Dev Tools.
Switch to the console.
Define an adhoc method:
var tryCatch = function (func) {
try {
func.apply(this, Array.prototype.slice.call(arguments, 1));
} catch (ex) {
var e = {
type: 'js',
message: ex.message,
detail: 'JS Error type: ' + ex.type + '<br/>\n' + 'Stack: ' + ex.stack
};
console.error(e);
}
};
Define a method which will throw an exception:
var myExceptionFunction = function () {
//Demo taken straight from ExtJs docs on Ext.menu.Menu
Ext.create('Ext.menu.Menu', {
width: 100,
margin: '0 0 10 0',
floating: false,
renderTo: 'thisIdDoesNotExist', //and will break the already rendered page
items: [{
text: 'regular item 1'
}, {
text: 'regular item 2'
}, {
text: 'regular item 3'
}]
});
};
Execute the myExceptionFunction method in the tryCatch wrapper:
tryCatch(myExceptionFunction);
Observe the reported error: "Cannot read property 'dom' of null"
Now start clicking back and forth between the opened tabs.
Suddenly, the page is exhibiting some odd behavior.
You begin to see new exceptions in the console: "Uncaught TypeError: Cannot read property 'dom' of undefined" Tabs render, but in unexpected places. The currently selected tab is not always properly updated.
Now, ExtJs's documentation site actually handles this fault quite well. Most of the page still works in ways that you can cope with; but in my scenario, my page is crippled.
We're talking about content that has already rendered--is already in the DOM.
I cannot imagine a reason for exceptions thrown past that point to break what has already executed.
Christopher, I'm sorry, but Evan's responses to your questions in your linked thread are all appropriate and make a lot of sense. He completely understands what you're asking for and you are not understanding him. Further research into the inner mechanisms of how Extjs is built would make you come to the realization that things 'already rendered' as you describe them are tightly linked to everything else that has to do with the layout engine. This is done for micro-optimizations that greatly improve render speed. Because it's so tightly linked together, when you try to render something to another thing that doesn't exist, you are going to bring the whole engine down.
The misunderstanding here is your assumption that things 'already rendered' have nothing to do with the things 'to be rendered.' In extjs these things are tightly coupled, and breaking one will break the other. Since this tight coupling is necessary to make the library render faster (believe me, they can't make it render any slower and still be usable on IE8), the 'issue' you are having is a necessary evil.
Evan's example of surrounding your code with a simple try-catch block is the best route if you are not able to or do not want to take the dev time to implement another solution within the logic of your own code.
I have a class that extends dijit.Dialog but only to set default functionality and buttons for my site. When clicking the dialog's cancel button the following code is run:
this.actionDialog.destroyRecursive();
this.actionDialog.destroy();
nb this.actionDialog = dijit.Dialog
Sometimes (not always) the following error gets thrown:
Uncaught TypeError: Cannot call method 'destroy' of undefined
DialogUnderlay.xd.js:8
Which causes following dialogs to incorrectly display. I am using 1.5 from Google API's. Am I missing something with the underlay code?
Error thrown after Ken's answer:
exception in animation handler for: onEnd
TypeError: Cannot read property 'style' of null
Both from dojo.xd.js:14. But the code still works properly.
I'm still not entirely sure what the problem is, other than for some reason dijit.DialogUnderlay code is getting confused. FWIW, this doesn't happen in Dojo 1.6.
While I was poking at some potential solutions, I seemed to accidentally find out that avoiding this problem is perhaps as easy as calling hide() on the dialog immediately before destroying it, e.g.:
this.actionDialog.hide();
this.actionDialog.destroyRecursive();
Alternatively, you might be interested in hiding the dialog, then destroying it once the hide animation finishes.
Here's how you can do it on Dojo 1.5 and earlier (tested 1.3+):
dlg.connect(dlg._fadeOut, 'onEnd', function() {
this.destroyRecursive();
});
dlg.hide();
In 1.6, the fadeOut animation is no longer exposed on the instance (granted, it was technically private earlier anyway), but onHide now triggers once the animation ends (whereas before it triggered as soon as it began). Unfortunately a setTimeout is needed to get around an error that occurs due to other code in the branch calling onHide, which assumes that something still exists on the instance which won't after we've destroyed it (see #12436).
dlg.connect(dlg, 'onHide', function() {
setTimeout(function() { dlg.destroyRecursive(); }, 0);
});
dlg.hide();
See it in action on JSFiddle: http://jsfiddle.net/3MNRu/1/ (See the initial version for the original error in the question)
The dialog.hide() method returns a Deferred, your code can be something more readable like this:
var dialog = this.actionDialog;
dialog.hide().then(function(){ dialog.destroyRecursive(); });
Be careful not to do this:
this.actionDialog.hide().then(function(){ this.actionDialog.destroyRecursive(); });
At the context of then this has another meaning!
You only need to call destroyRecursive()
The second destroy command is what is probably causing the error, and the error probably is causing the issues with other dialogs.
http://dojotoolkit.org/api/1.3/dijit/_Widget/destroyRecursive
destroyRecursive
Destroy this widget and it's descendants. This is the generic "destructor" function that all widget users should call to cleanly discard with a widget. Once a widget is destroyed, it's removed from the manager object.
I was getting the IE8 error : 'this.focusNode.form' is null or not an object. I found this was the result of the dialog.hide() returning a deferred. I wrote my own _closeDialog which eliminated the IE error.
_closeDialog : function(cntxt){
cntxt.popup.hide().then(
function(){
cntxt.popup.destroyRecursive(false);
cntxt.popup.destroy(false);
cntxt.destroyRecursive(false);
cntxt.destroy(false);
});
},