how to extend console functionality in javascript? - javascript

currently when we write console.log it print the msg.Can we extend the console functionality can we print current time with msg.I tried like this
(function () {
var old_console =console;
var newConsole = newconsole;
function newconsole() {
var d =new Date();
old_console.apply(this,arguments);
return d.getMilliseconds();
}
})();
but it is not working ..how can we print?

Create your own logging method rather than console and use that to spit out any format in console.log.
If you want to know timestamp of everything that is happening in console then just enable timestamps from console settings
see console.log timestamps in Chrome?
I have just run your code in fiddle with this options enabled in jsfiddle and got this
When I hover mouse over it, it also shows me date and time.
You can simply see it working with
/*Enable console settings to show timestamps and run this code*/
console.log('abc');
You dont need to extent log function to show time. Here is screenshot of new fiddle.

This works in Chrome inspector:
console.log = function(msg) {
var d = new Date();
return d.getMilliseconds() + ' ' + msg;
}
console.log('Hi');

myLogger = function(msg){
console.log(new Date()+" " +msg);
}
myLogger('Hi');
Simply create a wrapper for console.log which would also include a call new Date() responsible for printing the current date as well with the required log message.

You want to enhance console.log, so just address that method - not the whole console object.
(function (console) {
var old_log = console.log;
console.log = function() {
var d = new Date();
old_log.apply(console, [d].concat(arguments));
return d.getMilliseconds();
}
})(window.console);
If you want, you can do the same for console.error(), console.info(), console.log(), console.warn() etc. Here's an efficient way to do that :
(function (console, methods) {
var old = {};
methods.forEach(function(method) {
if(console[method]) {
old[method] = console[method];
console[method] = function() {
var d = new Date();
old[method].apply(console, [d].concat(arguments));
return d.getMilliseconds();
}
}
});
})(window.console, ['error', 'info', 'log', 'warn']);
With due consideration, you could probably do similar for further console methods.

Related

DEBUGGING: Code logs "undefined" when JSON is called with a variable

I have written in javascript something similar to the following, and I will try to reproduce my problem:
this.showInfo = function() {
var t = "";
var temp_family = query.t_family.toString();
var temp_category = query.t_category;
var temp_subcategory = query.t_subcategory;
$.getJSON("../javascript/stock.json", function(json) {
console.log("Good luck! JSON: ", json[temp_family], query.t_family.toString());
});
}
where query is a (dinamic??) object.
The issue is that when I log in the console the result from json[temp_family], logs undefined. But when I log query.t_family.toString() or simply json[{some_random_property}] (with a string of a property on the JSON file) it does log what I would expect...
What is my error here?

Return value from helperClass.js not making it back to index.js

Preface: I'm new to JavaScript. If this question is startlingly stupid, that's (part of) the reason.
Begin Update
I found the answer to my question prior to the flag as a dupe. I solved it with a try-catch block. This answer does not reference a try-catch block.
How do I return the response from an asynchronous call?
End Update
I'm attempting to create an Alexa project from scratch (well, at least without one of Amazon's templates). I've written the "guts" of the app and I've tested my functions with chai. Things were going swimmingly until I tried to wire up some intents.
I can see my intents are being sent based on console.log statements I've thrown in the helperClass, but the return values aren't making it back to my index.js file.
Two questions:
What am I mucking up?
How do I fix it?
Here's what I've done:
Based on that, I dug around to see what's going on in my index.js file's headers and I saw this:
var Alexa = require('alexa-app');
So I went to alexa-app and saw that it uses bluebird, which suggests to me that I'm dealing with a promise problem. Further, I saw this in the log when I send a request that works:
preRequest fired
postRequest fired
When a request doesn't work, I only see:
preRequest fired
I'm using Big Nerd Ranch's "Developing Alexa Skills Locally with Node.js".
Here's my problematic intent in my index.js file:
app.intent('getDaysFromNow', {
'slots': {
'INPUTDATE' : 'AMAZON.DATE'
},
'utterances': ['{|number of|how many} {days} {until|from|since} {|now|today} {|is|was} {-|INPUTDATE}'] // almost perfect
},
function(req, res) {
console.log('app.intent getDaysFromNow fired');
//get the slot
var inputDate = req.slot('INPUTDATE');
var reprompt = 'Ask me how many days until or from a specified date.';
if (_.isEmpty(inputDate)) {
console.console.log('app.intent daysFromNow blank request');
var prompt = 'I didn\'t hear the date you want.';
res.say(prompt).reprompt(reprompt).shouldEndSession(false);
return true;
} else {
console.log('getDaysFromNow slot is not empty.');
var dateHelper = new DateHelper();
dateHelper.getDaysFromNow(inputDate).then(function(daysFromNow) {
console.log(daysFromNow);
res.say(dateHelper.formatDaysFromNowResponse(daysFromNow)).send(); // FIXME
}).catch(function(err) {
console.log(err.statusCode);
var prompt = 'Hmm...I don\'t have a date for that ' + inputDate;
res.say(prompt).reprompt(reprompt).shouldEndSession(false).send();
});
return false;
}
}
);
I know it's getting sent, but the value's not getting back to index.js. I think I've got a return problem. Here's the function in my helperClass.js whose return isn't getting back to index.js
// Takes AMAZON.DATE string as its argument
DateHelper.prototype.getDaysFromNow = function(inputDate) {
if (isValidDate(inputDate)) { // validate it
// if it's valid, run the function
inputDate = moment(inputDate, "YYYY-MM-DD").startOf('day'); // inputDate starts as a string, recast as a moment here
// create currentDate moment from current Date()
var currentDate = moment(new Date()).startOf('day');
// Calculate daysFromNow here
var daysFromNow = inputDate.diff(currentDate, 'days');
console.log("\t" + 'daysFromNow = ' + daysFromNow);
// ORIGINAL CODE
// return daysFromNow;
// EXPERIMENTAL CODE
return this.daysFromNow.then(
function(response) {
return response.body;
}
);
} else {
// throw an error
throw new Error("getDaysFromNow(): argument must be valid AMAZON.DATE string");
}
};
Thank you for reading. I welcome your suggestions.
It turns out it's not the way the return is sent from helperClass. The issue is how the call was made in the first place.
For the helperClass, I reverted to the original return.
// This is the return from `helperClass`
return daysFromNow;
In the index.js class, I put the call to helperClass in a try-catch block, like so:
app.intent('getDaysFromNow', {
'slots': {
'INPUTDATE': 'AMAZON.DATE'
},
'utterances': ['{|number of|how many} {days} {until|from|since} {|now|today} {|is|was} {-|INPUTDATE}'] // almost perfect
},
function(req, res) {
console.log('app.intent getDaysFromNow fired');
//get the slot
var inputDate = req.slot('INPUTDATE');
var reprompt = 'Ask me how many days until or from a specified date.';
if (_.isEmpty(inputDate)) {
console.log('app.intent daysFromNow blank request');
var prompt = 'I didn\'t hear the date you want.';
res.say(prompt).reprompt(reprompt).shouldEndSession(false);
return true;
} else {
// ** CHANGED: This is the part that changed. **
console.log('getDaysFromNow slot is not empty.');
var dateHelper = new DateHelper();
try {
var daysFromNow = dateHelper.getDaysFromNow(inputDate);
res.say(dateHelper.formatDaysFromNowResponse(daysFromNow)).send();
} catch (error) {
console.log("error", error);
var prompt = 'Hmm...I don\'t have a date for that ' + inputDate;
res.say(prompt).reprompt(reprompt).shouldEndSession(false).send();
}
return false;
}
}
);
Hopefully, someone finds this helpful if they run into the same problem.

Javascript run faster if console opened

i'm developing a phonegap app using a lot of javascript. Now i'm debugging it using Safari Developer Tool, in particular i'm focused on some button that on the device seems to be a bit luggy.
So I've added some console.timeEnd() to better understand where the code slow down, but the "problem" is that when i open the console the code start running faster without lag, if i close it again, the lag is back.
Maybe my question is silly but i can't figure it out
Thanks
EDIT: Added the code
function scriviNumeroTastiera(tasto){
console.time('Funzione ScriviNumeroTastiera');
contenutoInput = document.getElementById('artInserito').value;
if ($('#cursoreImg').css('display') == 'none'){
//$('#cursoreImg').show();
}
else if (tasto == 'cancella'){
//alert(contenutoInput.length);
if (contenutoInput.length == 0) {
}
else {
indicePerTaglioStringa = (contenutoInput.length)-1;
contenutoInput = contenutoInput.substr(0, indicePerTaglioStringa);
$('#artInserito').val(contenutoInput);
//alert('tastoCanc');
margineAttualeImg = $('#cursoreImg').css('margin-left');
indicePerTaglioStringa = margineAttualeImg.indexOf('p');
margineAttualeImg = margineAttualeImg.substr(0, indicePerTaglioStringa);
margineAggiornato = parseInt(margineAttualeImg)-20;
$('#cursoreImg').css('margin-left', margineAggiornato+'px');
}
}
else {
//contenutoInput = document.getElementById('artInserito').value;
contenutoAggiornato = contenutoInput+tasto;
margineAttualeImg = $('#cursoreImg').css('margin-left');
indicePerTaglioStringa = margineAttualeImg.indexOf('p');
margineAttualeImg = margineAttualeImg.substr(0, indicePerTaglioStringa);
margineAggiornato = parseInt(margineAttualeImg)+20;
$('#cursoreImg').css('margin-left', margineAggiornato+'px');
$('#artInserito').val(contenutoAggiornato);
}
console.timeEnd('Funzione ScriviNumeroTastiera');
}
The code is a bit crappy, but it's just a beginning ;)
This could happen because PhoneGap/Cordova creates its own console object (in cordova.js), and it gets overwritten when you open the Safari console (safari's might be faster than phonegap's, that could be why you notice it faster).
So, one way to measure the time properly, without opening the console, would be to go to the good old alert, so you'd first add this code anywhere in your app:
var TIMER = {
start: function(name, reset){
if(!name) { return; }
var time = new Date().getTime();
if(!TIMER.stimeCounters) { TIMER.stimeCounters = {} };
var key = "KEY" + name.toString();
if(!reset && TIMER.stimeCounters[key]) { return; }
TIMER.stimeCounters[key] = time;
},
end: function(name){
var time = new Date().getTime();
if(!TIMER.stimeCounters) { return; }
var key = "KEY" + name.toString();
var timeCounter = TIMER.stimeCounters[key];
if(timeCounter) {
var diff = time - timeCounter;
var label = name + ": " + diff + "ms";
console.info(label);
delete TIMER.stimeCounters[key];
}
return diff;
}
};
(This just mimics the console.time and console.timeEnd methods, but it returns the value so we can alert it).
Then, instead of calling:
console.time('Funzione ScriviNumeroTastiera');
you'd call:
TIMER.start('Funzione ScriviNumeroTastiera');
and instead of calling:
console.timeEnd('Funzione ScriviNumeroTastiera');
you'd call:
var timeScriviNumeroTastiera = TIMER.end('Funzione ScriviNumeroTastiera');
alert('Ellapsed time: ' + timeScriviNumeroTastiera);
This would give you the proper ellapsed time without opening the console, so it computes the real time in the phonegap app.
Hope this helps.
Cheers
This really isn't something you would normally expect - opening the console should not speed up anything. If anything, it will make things slower because of additional debugging hooks and status display. However, I've had a case like that myself. The reason turned out to be very simple: opening the console makes the displayed portion of the website smaller and the code efficiency was largely dependent on the viewport size. So if I am right, making the browser window smaller should have the same effect as opening the console.

How to read from Chrome's console in JavaScript

I would like to put a button in my app, if you press it it will get the contents of everything that was written to the console and email it to me (for reporting bugs). I know I can keep a variable around and every time I do a console.log also append the message to that variable but I am trying to keep the memory consumption of the app low so it would be much more efficient just to grab it from the console.
Is there a way to retrieve the console messages from javascript?
You can't. What's in the console can't be read from JavaScript.
What you can do is hook the console.log function so that you store when it logs :
console.stdlog = console.log.bind(console);
console.logs = [];
console.log = function(){
console.logs.push(Array.from(arguments));
console.stdlog.apply(console, arguments);
}
console.logs contains all what was logged. You can clean it at any time by doing console.logs.length = 0;.
You can still do a standard, non storing, log by calling console.stdlog.
get all console data
how to read browser console error in js?
How to read from Chrome's console in JavaScript
https://www.quora.com/How-do-I-read-console-window-errors-from-Chrome-using-JavaScript
logs
console.defaultLog = console.log.bind(console);
console.logs = [];
console.log = function(){
// default & console.log()
console.defaultLog.apply(console, arguments);
// new & array data
console.logs.push(Array.from(arguments));
}
error
console.defaultError = console.error.bind(console);
console.errors = [];
console.error = function(){
// default & console.error()
console.defaultError.apply(console, arguments);
// new & array data
console.errors.push(Array.from(arguments));
}
warn
console.defaultWarn = console.warn.bind(console);
console.warns = [];
console.warn = function(){
// default & console.warn()
console.defaultWarn.apply(console, arguments);
// new & array data
console.warns.push(Array.from(arguments));
}
debug
console.defaultDebug = console.debug.bind(console);
console.debugs = [];
console.debug = function(){
// default & console.debug()
console.defaultDebug.apply(console, arguments);
// new & array data
console.debugs.push(Array.from(arguments));
}
I have used this code in the past to capture all console activity and store it with types and timestamps in console.everything for sending back to the server for diagnosing form data entry issues. I run this code as early as possible in the <head> element.
if (console.everything === undefined)
{
console.everything = [];
console.defaultLog = console.log.bind(console);
console.log = function(){
console.everything.push({"type":"log", "datetime":Date().toLocaleString(), "value":Array.from(arguments)});
console.defaultLog.apply(console, arguments);
}
console.defaultError = console.error.bind(console);
console.error = function(){
console.everything.push({"type":"error", "datetime":Date().toLocaleString(), "value":Array.from(arguments)});
console.defaultError.apply(console, arguments);
}
console.defaultWarn = console.warn.bind(console);
console.warn = function(){
console.everything.push({"type":"warn", "datetime":Date().toLocaleString(), "value":Array.from(arguments)});
console.defaultWarn.apply(console, arguments);
}
console.defaultDebug = console.debug.bind(console);
console.debug = function(){
console.everything.push({"type":"debug", "datetime":Date().toLocaleString(), "value":Array.from(arguments)});
console.defaultDebug.apply(console, arguments);
}
}
QA Collective's solution is very nice but has a lot of repeated code and doesn't capture errors that are not printed via the console.log, console.error, etc.
Here's the DRY and extended version of his solution that captures more error messages that show up in the console:
if (console.everything === undefined) {
console.everything = [];
function TS(){
return (new Date).toLocaleString("sv", { timeZone: 'UTC' }) + "Z"
}
window.onerror = function (error, url, line) {
console.everything.push({
type: "exception",
timeStamp: TS(),
value: { error, url, line }
})
return false;
}
window.onunhandledrejection = function (e) {
console.everything.push({
type: "promiseRejection",
timeStamp: TS(),
value: e.reason
})
}
function hookLogType(logType) {
const original= console[logType].bind(console)
return function(){
console.everything.push({
type: logType,
timeStamp: TS(),
value: Array.from(arguments)
})
original.apply(console, arguments)
}
}
['log', 'error', 'warn', 'debug'].forEach(logType=>{
console[logType] = hookLogType(logType)
})
}
I also changed the timestamp format to use the ISO format in UTC timezone, to be able to compare time stamps in different time zones more easily.
If you're working on vue.js, you can actually do this:
data () {
return {
data: []
}
},
created () {
let current_log = console.log;
console.log = msg => {
if (msg !== undefined) this.data.push(msg);
current_log.apply(null, arguments);
}
}
All logs from console will be captured and stored in data
If you just want to catch windows errors (Browser's developer tool), you just need to use the window.onerror listener. and the most important thing is to keep returning it false because If you return true in your callback, then the propagation of the error will stop and won't be log in the console anymore .
window.onerror = function myErrorHandler(err, url, line) {
//Do some stuff
console.log(err) // Uncaught SyntaxError: Invalid or unexpected token at Line no:- 1
return false; // so you still log errors into console
}

Showing console errors and alerts in a div inside the page

I'm building a debugging tool for my web app and I need to show console errors in a div. I know I can use my own made console like object and use it, but for future use I need to send all console errors to window. Actually I want to catch console events.
To keep the console working:
if (typeof console != "undefined")
if (typeof console.log != 'undefined')
console.olog = console.log;
else
console.olog = function() {};
console.log = function(message) {
console.olog(message);
$('#debugDiv').append('<p>' + message + '</p>');
};
console.error = console.debug = console.info = console.log
Here's a way using closure, containing the old console log function in the scope of the new one.
console.log = (function (old_function, div_log) {
return function (text) {
old_function(text);
div_log.value += text;
};
} (console.log.bind(console), document.getElementById("error-log")));
None of the answers here consider console messages that get passed multiple parameters. E.g. console.log("Error:", "error details")).
The function that replaces the default log function better regards all function arguments (e.g. by using the arguments object). Here is an example:
console.log = function() {
log.textContent += Array.prototype.slice.call(arguments).join(' ');
}
(The Array.prototype.slice.call(...) simply converts the arguments object to an array, so it can be concatenated easily with join().)
When the original log should be kept working as well:
console.log = (function (old_log, log) {
return function () {
log.textContent += Array.prototype.slice.call(arguments).join(' ');
old_log.apply(console, arguments);
};
} (console.log.bind(console), document.querySelector('#log')));
A complete solution:
var log = document.querySelector('#log');
['log','debug','info','warn','error'].forEach(function (verb) {
console[verb] = (function (method, verb, log) {
return function () {
method.apply(console, arguments);
var msg = document.createElement('div');
msg.classList.add(verb);
msg.textContent = verb + ': ' + Array.prototype.slice.call(arguments).join(' ');
log.appendChild(msg);
};
})(console[verb], verb, log);
});
(An example of a framework that emits messages with multiple parameters is Video.js. But there is certainly many others.)
Edit: Another use of multiple parameters is the formatting capabilities of the console (e.g. console.log("Status code: %d", code).
About errors that are not shown
(Update Dec. 2021)
If any code crashes with an uncaught error, in might not show up in the div. One solution could be, if possible, to wrap all code in a try block to catch such errors and log them manually to the div.
try {
// Code that might throw errors...
} catch(err) {
// Pass the error to the overridden error log handler
console.error(err);
}
Else, if you were concerned at keeping log, warn and error separate from one another, you could do something like this (adapted from MST's answer):
var log = document.querySelector('#log');
['log','warn','error'].forEach(function (verb) {
console[verb] = (function (method, verb, log) {
return function (text) {
method(text);
// handle distinguishing between methods any way you'd like
var msg = document.createElement('code');
msg.classList.add(verb);
msg.textContent = verb + ': ' + text;
log.appendChild(msg);
};
})(console[verb].bind(console), verb, log);
});
where #log is your HTML element. The variable verb is one of 'log', 'warn', or 'error'. You can then use CSS to style the text in a distinguishable way. Note that a lot of this code isn't compatible with old versions of IE.
How about something as simple as:
console.log = function(message) {$('#debugDiv').append('<p>' + message + '</p>');};
console.error = console.debug = console.info = console.log
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<div id="logger" class="web_console"></div>
<script type="text/javascript">
// Overriding console object
var console = {};
// Getting div to insert logs
var logger = document.getElementById("logger");
// Adding log method from our console object
console.log = function(text)
{
var element = document.createElement("div");
var txt = document.createTextNode(text);
element.appendChild(txt);
logger.appendChild(element);
}
// testing
console.log("Hello World...");
console.log("WOW");
/**
console.log prints the message in the page instead browser console, useful to programming and debugging JS using a Android phone
*/
</script>
</body>
</html>
I created a zero-dependency npm module for this case: console-events (surely if you're okay to use nodejs :P)
You can add event listener like that:
const { console } = require('console-events');
console.addEventListener('log', (e) => {
e.preventDefault(); //if you need to prevent normal behaviour e.g. output to devtools console
$('#debugDiv').append('<p>' + message + '</p>');
})

Categories