How do I get the message/details with addeventlistener("error")?

Asked

Viewed 768 times

7

When I define true in the parameter useCapture:

addEventListener(type, listener[, useCapture]);

I can catch any mistake, however I can’t get the details of error, see:

window.addEventListener('error', function(e) {
    console.log(e);
}, true);

But in the console I reviewed the event (variable e) and there’s the message with details, the only thing I can see is the target.

I tried to use this:

window.onerror = function(msg, err, line) {
    console.log(msg, err, line);
};

But the problem is window.onerror does not capture all events, for example HTTP errors.

Suppose I call a script that doesn’t exist like this <script src="foo.js"></script>, the window.onerror does not fire and there is no way I can add manually, taking into account that certain libraries carry things like <img>, <script> and <iframe> dynamically.

Note that I tried to add <script src="foo.js" onerror="alert(arguments[0]);"></script>, just to test, but it works different from window.onerror and does not capture the error message.

Is there any way to capture any error (such as errors from parse and HTTP errors), or this is impossible?

  • @Guilhermenascimento From a look in that article, of an attention in the Capture the Stack, where the property is mentioned stack. Maybe it’ll help something.

  • @zekk seems that unfortunately the event.error is only available for things like "parse", for things like new Image(); or DOM elements it always returns undefined

  • 1

    Maybe - and this is just a guess - errors like these that you want to capture only exist in the capture phase, and not in the bubbling phase (so use useCapture false does not catch these errors). And if the error handling in the capture phase is substantially different from the bubbling phase, maybe these "error details" don’t even exist in the way you expect. It would take someone with more experience to comment, because from what I see the capture phase is rarely used (I myself cost to discover that it even existed), which makes it difficult to find details of its operation.

  • 1

    @mgibsonbr I think this correct, I mean, not by useCapture, but by the moment, assuming there is an Interface called Errorevent, it must be Generica, being an error in javascript it will have more properties in the object, being HTTP error it will use only the basic interface to trigger the event. For example, as zekk said, some properties were only implemented after.

1 answer

4

We need to divide the types of events. Errors of HTTP and of compilation.
They are detected/captured differently.

I will refer first to HTTP errors which I believe is the focus of the question, and then I refer to other very inspired by this response in the Soen.

HTTP

When we have an external resource that needs to be loaded, it can happen that this feature fails to load. Because it could not be downloaded, or because its content could not be interpreted/compiled, ie is not executable.

These errors are hard to detect and we don’t know much about them.

There are several ways to load external components. Via HTML with tags like script, img, link, via AJAX or for example via iframe.

Clicking on the document with script, img, link

When a resource does not load we can detect it globally or locally in the tag.

I’ve been comparing the events we received from window.addEventListener('error', and <script onerror= and it seems to me that you both have the same information.

		// usei este script para percorrer os eventos e comparar 
		// o seu conteúdo nos dois primeiros níveis
        for (var k in e) {
            if (e[k] &&typeof e[k] == 'string') console.log(k, e[k])
            if (typeof e[k] == 'object') {
                for (var p in e[k]) {
                    if (e[k][p] && typeof e[k][p] == 'string') console.log(p, e[k][p])
                }
            }
        }

Thus using:

window.addEventListener('error', function(e) {
    getDetails(e, 'global');
}, true);

or using:

<div onerror="console.log(event, 'div')">
    <script onerror="getDetails(event, 'script')" src="lfdghjdf.js"></script>
</div>

I get the same results. Of course <div onerror is never called because the event error is not propagated in the DOM.

The test I took was:

<script>
    function getDetails(e, where) {
        var info = {
            targetInfo: {}
        };
        var props = ["type", "bubbles", "cancelable", "view", "detail", "message"];
        props.forEach(function(prop) {
            info[prop] = e[prop];
        });

        ["tagName", "outerHTML", "src"].forEach(function(prop) {
            info.targetInfo[prop] = e.target[prop];
        });
        info.targetInfo.srcValue = e.target.attributes.src.value;
        var json = JSON.stringify(info, null, 4);
        console.log(where);
        console.log(json);
        console.log('-----------------');
    }
    window.addEventListener('error', function(e) {
        getDetails(e, 'global');
    }, true);

</script>

<div onerror="console.log(event, 'div')">
    <script onerror="getDetails(event, 'script')" src="lfdghjdf.js"></script>
</div>

And the result:

global
{
    "targetInfo": {
        "tagName": "SCRIPT",
        "outerHTML": "<script onerror=\"getDetails(event, 'script')\" src=\"lfdghjdf.js\"></script>",
        "src": "https://fiddle.jshell.net/toyubp9L/show/lfdghjdf.js",
        "srcValue": "lfdghjdf.js"
    },
    "type": "error",
    "bubbles": false,
    "cancelable": false
}
-----------------
{
    "targetInfo": {
        "tagName": "SCRIPT",
        "outerHTML": "<script onerror=\"getDetails(event, 'script')\" src=\"lfdghjdf.js\"></script>",
        "src": "https://fiddle.jshell.net/toyubp9L/show/lfdghjdf.js",
        "srcValue": "lfdghjdf.js"
    },
    "type": "error",
    "bubbles": false,
    "cancelable": false
}

This method detects resource access failures, to fail to compile phallus in the next section.

Loading via iframe

Here we are with our hands tied. As far as I know, no access to window of iframe there is no way to know that an error has occurred.

Loading via AJAX

Assuming that we load all external resources via AJAX it is possible which component had problems because we can isolate each component much better. I won’t stretch with ajax for now, but ajax has its own event error that we can use and once we call a resource one to one we know which failure.

Compilation errors

Here we have more information about what is happening because the browser tries to compile code and when it fails to share via window.onerror.

Note that the window.onerror receives much more information than the elemento.onerror, hence it is preferable to debug.

The types of error it records:

unspoken mistakes

  • Throw "messages from the browser"
  • variables();
  • cross_origin_iframe.contentWindow.Document;, security holes like CORS

compilation errors

  • <script>{</script>
  • <script>for(;)</script>
  • <script>"oops</script>
  • setTimeout("{", 10);, because "{" will be compiled with script

An example of code that will give build error (parse error) could be:

function foo(){

{{{...

or more natural to happen:

var hoje = new Date();
alert(hoj); // esqueci o "e"

This could be detected with

window.onerror = function(msg, url, line, col, error) {
   // col & error são recentes, inseriram-se no HTML5
   var extra = !col ? '' : '\ncolumn: ' + col;
   extra += !error ? '' : '\nerror: ' + error;
   alert("Error: " + msg + "\nurl: " + url + "\nline: " + line + extra);
   return true; // para evitar alert no IE
};

An example would be:

<script>
    window.onerror = function(msg, url, line, col, error) {
        // col & error são recentes, inseriram-se no HTML5
        var extra = !col ? '' : '\ncolumn: ' + col;
        extra += !error ? '' : '\nerror: ' + error;
        alert("Error: " + msg + "\nurl: " + url + "\nline: " + line + extra);
        return true; // para evitar alert no IE
    };

</script>
<script>!{..</script>

This method can be very useful for local scripts, and with this information send for example with AJAX error information to the server and thus detect errors in the clients.

However, if the script that has build problems is external, it will be interpreted/compiled in the global context and we can’t get anything out of it... only it happened.


Note:

The addEventListener does not detect build errors. That is why I use this method. The onerror is better at compiling errors because it passes more arguments.

Here’s an example I tried in Chrome: https://jsfiddle.net/bj7478g4/

References:

(In English)

  • Any particular reason to use window.addEventListener('error', callback) for errors in HTML and window.onerror for compilation errors? apparently the window.addEventListener('error', callback) can also handle compilation errors.: https://jsfiddle.net/TobyMosque/6vou4rdy/

  • @Tobymosque yes, I added that to the answer.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.