3

Is there a way to subscribe on some console event from javascript on a page?

Usecase: I want to see an alert window on any js error

something like:

console.on('error', => alert('There is an error! Look in console window'))
console.on('log', => alert('Something log to console'))

NB: I don't ask about catching an exception.

kharandziuk
  • 12,020
  • 17
  • 63
  • 121
  • Possible Duplicate. Kindly refer [Global JS Exception Handler](http://stackoverflow.com/questions/951791/javascript-global-error-handling) – Rajesh Oct 27 '15 at 13:35
  • no, it isn`t a duplicate – kharandziuk Oct 27 '15 at 13:38
  • 1
    There is no such thing, at least on chrome console. https://developer.chrome.com/devtools/docs/console-api – Miguel Lattuada Oct 27 '15 at 13:38
  • 1
    For the latter just redefine `console.log` to your own function (then applying it to a saved reference to the original) For errors this is more difficult to handle with script in the case of errors that halt script execution ... – Alex K. Oct 27 '15 at 13:39
  • Why not send the alert in the javascript code and write the error to console line? – Joakim M Oct 27 '15 at 13:46
  • 1
    You can try following [StackOverflow Article](http://stackoverflow.com/questions/601363/reading-the-firebug-console-in-javascript). One way shown is to override console.log itself. But I don't know its the right approach. – Rajesh Oct 27 '15 at 14:07
  • @Rajesh I guess it doesn't work in case of an error – kharandziuk Oct 27 '15 at 14:10

2 Answers2

2

Following instructions on the link in my previous comment, I have created a JSFiddle - Override Console methods.

I still don't know if this is the best way, but this seems to work.

Edit

After discussion, I understood, problem was not just about catching all console messages but to also capture any unhandled errors. In my understanding only way to achieve is to add a Global Exception Handler

window.onerror = function(error){
    // do your stuff
}

Following is the Updated JSFiddle. I also have updated the code snippet to show the same.

Code

var error = window.console.error,
 log = console.log,
    info = console.info,
    warn = console.warn;
var lastLog = "", 
    lastError="",
    lastInfo="",
    lastWarn="";

function overrideConsole(){
    console.error = function () {
        lastError = arguments;
        //alert(lastError);
        print(lastError, "error")
        error.apply(console, arguments);
    };
    
    console.log = function () {
        lastLog = arguments;
        print(lastLog, "log");
        log.apply(console, arguments);
    };
    
    console.info = function () {
        lastInfo = arguments;
        print(lastInfo, "info");
        info.apply(console, arguments);
    };
    
    console.warn = function () {
        lastWarn = arguments;
        print(lastWarn, "warn");
        warn.apply(console, arguments);
    };
}

function registerEvents(){
 $("#btnError").on("click", function(){
     console.error("new error");
    });
    
    $("#btnLog").on("click", function(){
     console.log("new log");
    });
    
    $("#btnInfo").on("click", function(){
     console.info("new info");
    });
    
    $("#btnWarn").on("click", function(){
     console.warn("new warn");
    });
    
    $("#btnException").on("click", function(){
     throw new Error();
    });
}

function registerGlobalHandler(){
 window.onerror = function(error) {
     console.error(error);
 };
}

function print(str, type){
    var msgClass= "";
    
    switch(type){
        case "log": msgClass=" log"; break;
        case "error": msgClass=" error"; break;
        case "info": msgClass=" info"; break;
        case "warn": msgClass=" warn"; break;
    }
 var div = "<div class='cell'>"+
         "<label class='"+msgClass+"'>"+ str[0]+"</label>" +
        "</div>"
    $(".content").html( div + $(".content").html());
}

(function init(){
 registerEvents();
    registerGlobalHandler();
    overrideConsole();
  
    // Undefined function call
    test();
})();
.cell{
    width:90%;
    position:relative;
    padding:5px;
    background: #eee;
}

.info{
    color:blue;
}
.error{
    color:red;
}
.warn{
    color:green;
}
.log{
    color:black;
}
.content{
    width:90%;
    height:300%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button id="btnError">Error</button>
<button id="btnLog">Log</button>
<button id="btnInfo">Info</button>
<button id="btnWarn">Warn</button>
<button id="btnException">Exception</button>

<div class="content"></div>
Community
  • 1
  • 1
Rajesh
  • 24,354
  • 5
  • 48
  • 79
  • I mean a real error(instead of error message). try to evaluate somewhere on page: ``` var a = {}; a.fun(); ``` Do you see any error? – kharandziuk Oct 27 '15 at 14:56
  • Per my understanding, anything that is logged through `console` will be captured. The case that you mentioned will not be captured because it is unhandled exception. [Updated JSFiddle](http://jsfiddle.net/RajeshDixit/avp9zvgu/2/) for same. For such cases, you will have to handle them. This is where Global Exception Handler comes to play. Also I guess this might help. [MDN JS Shell](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Introduction_to_the_JavaScript_shell#readline%28%29). – Rajesh Oct 27 '15 at 15:05
0

As has been pointed out, there is no global way (that I know of) to subscribe to console events. A partial solution for logging would be to override the console as described by @Rajesh's answer.

For error checking, if you own the code you're trying to check errors for, you can wrap the whole thing in an global try/catch.

try {

  (function() {
    function failingCode() {
      var a;
      return a.foo + 1;

    }

    failingCode();
  })();

}
catch (err) {
  alert('error');
  throw err;
}

For third-party scripts, I can't think of any way of handling this except to load the script via a mechanism like jQuery's getScript. And I'm unclear what happens if that script itself loads additional scripts.

Palpatim
  • 9,074
  • 35
  • 43