This question already has answers here:
Capturing javascript console.log? [duplicate]
(2 answers)
Closed 4 years ago.
I have been seeing in some questions on Stack Overflow that there is examples, example code or snippets. Such as the one below:
console.log(1, 2, 3)
By running the code snippet above you'll see something like this:
I am currently working with something in node.js that also requires to fetch the output from console.logs. I find it fascinating that Stack Overflow is able to do this, whilst I don't even have a single clue how they did this.
I would be very thankful if someone could send me a link to where I can read and learn about how to fetch data form the console API.
Cheers,
Richard
P.S. If someone could edit this post to display the image, I'd be very thankful.
Edit
The project that I'm working on is an Electron app. It uses both the node.js process and the Electron BrowserWindow.
It uses a logger that I'm working on wich needs to fetch data from console.log
Some of the use cases might look like this:
console.log('%d is cool', User.firstName)
// => "Jason is cool"
or
console.log('User ID:', User._id)
// => A5FFE
or
console.log('%cUser connected!', 'color: #00FF00')
// => User connected!
// In green text.
You can overwrite window.console.log with your own function to achieve such an effect. For example:
const oldConsoleLog = console.log.bind(console);
console.log = (...params) => {
const textToDisplay = params.map(param =>
typeof param === 'object'
? JSON.stringify(param)
: param
);
document.body.appendChild(document.createElement('div'))
.textContent = textToDisplay;
oldConsoleLog(...params);
};
console.log('foo');
console.log('bar baz');
console.log({ prop: 'value' });
.as-console-wrapper {
height: 60%
}
In nodejs, console.log just formats the data you pass to it and then writes it to process.stdout which is a stream that goes to your commandline window. To intercept that, you can just listen for events on that stream:
process.stdout.on("data", chunk => {
// Do what you wanna do
});
Related
This question already has answers here:
Puppeteer log inside page.evaluate
(13 answers)
Closed 1 year ago.
Here, I am trying to get each players runs and matches using player-URL.
When I passes selector within page.$$eval method and in callback element when I console it,I got nothing in it.
const stats = await page.$$eval(
"div.score-top.sp.text-center > div.container > div.match-summary > div.row > div.col-sm-12 > div.match-in-summary > div.row > div.col-sm-5 > div.matches-runs-wickets > ul.list-inline ",
(elements) => {
console.log("elements", elements);
return elements.map((match) => {
return (obj = {
matches: match.querySelector(" li:nth-Child(1) >span").innerText,
runs: match.querySelector("li:nth-Child(2) > span").innerText,
});
});
}
);
return stats;
}
but when I map over the callback element and return the object then I am getting runs and matches in stats variableThe code detail is mentioned here.
Everything that you console.log in eval function will be displayed in browser's console. See the console of the browser that you have opened and there you will see the logs that you are trying to print.
In your example console.log is happening not on the node.js side, but inside of a headless browser's console. You can see messages if you launch puppeteer with headless: false option.
And if you'd like to receive such console messages in terminal, see this answer.
I'm building a very simple scraper to get the 'now playing' info from an online radio station I like to listen too.
It's stored in a simple p element on their site:
data html location
Now using the standard apify/web-scraper I run into a strange issue. The scraping sometimes works, but sometimes doesn't using this code:
async function pageFunction(context) {
const { request, log, jQuery } = context;
const $ = jQuery;
const nowPlaying = $('p.js-playing-now').text();
return {
nowPlaying
};
}
If the scraper works I get this result:
[{"nowPlaying": "Hangover Hotline - hosted by Lamebrane"}]
But if it doesn't I get this:
[{"nowPlaying": ""}]
And there is only a 5 minute difference between the two scrapes. The website doesn't change, the data is always presented in the same way. I tried checking all the boxes to circumvent security and different mixes of options (Use Chrome, Use Stealth, Ignore SSL errors, Ignore CORS and CSP) but that doesn't seem to fix it unfortunately.
Scraping instable
Any suggestions on how I can get this scraping task to constantly return the data I need?
It would be great if you can attach the URL, it will help me to find out the problem.
With the information you provided, I guess that the data you want to are loaded asynchronously. You can use context.waitFor() function.
async function pageFunction(context) {
const { request, log, jQuery } = context;
const $ = jQuery;
await context.waitFor(() => !!$('p.js-playing-now').text());
const nowPlaying = $('p.js-playing-now').text();
return {
nowPlaying
};
}
You can pass the function to wait, and I will wait until the result of the function will be true. You can check the doc.
This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Iterate array and wait for promises
(1 answer)
Closed 4 years ago.
While I have been working in python for quite some time, I've recently started working with javascript for its tight integration with Web.
I am still struggling with concepts of event driven programming and promise driven function.
Anyway, Below I am using node.js module is-port-reachable.
It does a good job of returning status if given host is reachable over a given port or not.
However, I need to collect combined info of host and port status.
For e.g. if I have hosts = ['hostA' , 'hostB' ];
I need to collect status of its port scan status as
hosts2 = [ ('hostA' , true) , ('hostB', false)];
With below code, I am able to get individual status of port scan for each host, but when I try to add it to array host2, its coming back as empty.
It seems promise function is not able to take/recognize external variable aHost.
const isPortReachable = require('is-port-reachable');
hosts = [ 'host' , 'host2'];
var hosts2 = new Array();
for ( var l = 0; l < hosts.length; l++) {
var aHost = hosts[l];
const myFunction = (aHost) =>{
return isPortReachable(8443, {host: aHost})
};
myFunction(aHost).then(result => {
console.log(aHost, result);
hosts2.push((aHost,result));
});
}
console.log(hosts2);
Output:
Further, Looks like console.log(hosts2); is getting executed before for loop.
node myscript.js
[]
hostA true
hostB false
Any help is appreciated.
I had a little freetime so I decided to rewrite all my bash scripts in JavaScript (NodeJS - ES6) with child processes. Everything went smoothly until I wanted to automate user input.
Yes, you can do automate the user input. But there is one Problem - you can't determine if the given data event is a feedback or a request for input. At least I can't find a way to do it.
So basically you can do this:
// new Spawn.
let spawn = require('child_process');
// new ufw process.
let ufw = spawn('ufw', ['enable']);
// Use defined input.
ufw.stdin.setEncoding('utf-8');
ufw.stdout.pipe(process.stdout);
ufw.stdin.write('y\n');
// Event Standard Out.
ufw.stdout.on('data', (data) => {
console.log(data.toString('utf8'));
});
// Event Standard Error.
ufw.stderr.on('data', (err) => {
// Logerror.
console.log(err);
});
// When job is finished (with or without error) it ends up here.
ufw.on('close', (code) => {
// Check if there were errors.
if (code !== 0) console.log('Exited with code: ' + code.toString());
// End input stream.
ufw.stdin.end();
});
The above example works totally fine. But there are 2 things giving me an headache:
Will ufw.stdin.write('y\n'); wait until it is needed and what happens if I have multiple inputs? For example 'yes', 'yes', 'no'. Do I have to write 3 lines of stdin.write()?
Isn't the position where I use ufw.stdin.write('y\n'); a little confusing? I thought I need the input after my prompt made a request for input so I decided to change my code that my stdin.write() could run at the right time, makes sense right? However the only way to check when the 'right' time is on the stdout.on('data', callback) event. That makes thinks a little difficult, since I need to know if the prompt is aksing for user input or not...
Here is my code which I think is totally wrong:
// new Spawn.
let spawn = require('child_process');
// new ufw process.
let ufw = spawn('ufw', ['enable']);
// Event Standard Out.
ufw.stdout.on('data', (data) => {
console.log(data.toString('utf8'));
// Use defined input.
ufw.stdin.setEncoding('utf-8');
ufw.stdout.pipe(process.stdout);
ufw.stdin.write('y\n');
});
// Event Standard Error.
ufw.stderr.on('data', (err) => {
// Logerror.
console.log(err);
});
// When job is finished (with or without error) it ends up here.
ufw.on('close', (code) => {
// Check if there were errors.
if (code !== 0) console.log('Exited with code: ' + code.toString());
// End input stream.
ufw.stdin.end();
});
My major misunderstanding is when to use stdin for user input (automated) and where to place it in my code so it will be used at the right time, for example if I have multiple inputs for something like mysql_secure_installation.
So I was wondering if it is possible and it seems not. I posted an issue for node which ended up beeing closed: https://github.com/nodejs/node/issues/16214
I am asking for a way to determine if the current process is waiting for an input.
There isn't one. I think you have wrong expectations about pipe I/O
because that's simply not how it works.
Talking about expectations, check out expect. There is probably a
node.js port if you look around.
I'll close this out because it's not implementable as a feature, and
as a question nodejs/help is the more appropriate place.
So if anyone has the same problem as I had you can simply write multiple lines into stdin and use that as predefined values. Keep in mind that will eventually break the stream if any input is broken or wrong in feature updates:
// new Spawn.
let spawn = require('child_process');
// new msqlsec process.
let msqlsec = spawn('mysql_secure_installation', ['']);
// Arguments as Array.
let inputArgs = ['password', 'n', 'y', 'y', 'y', 'y'];
// Set correct encodings for logging.
msqlsec.stdin.setEncoding('utf-8');
msqlsec.stdout.setEncoding('utf-8');
msqlsec.stderr.setEncoding('utf-8');
// Use defined input and write line for each of them.
for (let a = 0; a < inputArgs.length; a++) {
msqlsec.stdin.write(inputArgs[a] + '\n');
}
// Event Standard Out.
msqlsec.stdout.on('data', (data) => {
console.log(data.toString('utf8'));
});
// Event Standard Error.
msqlsec.stderr.on('data', (err) => {
// Logerror.
console.log(err);
});
// When job is finished (with or without error) it ends up here.
msqlsec.on('close', (code) => {
// Check if there were errors.
if (code !== 0) console.log('Exited with code: ' + code.toString());
// close input to writeable stream.
msqlsec.stdin.end();
});
For the sake of completeness if someone wants to fill the user input manually you can simply start the given process like this:
// new msqlsec process.
let msqlsec = spawn('mysql_secure_installation', [''], { stdio: 'inherit', shell: true });
This question already has an answer here:
after updating chrome(35.0.1916.114 m), webkitNotifications does not work
(1 answer)
Closed 7 years ago.
I have a extension that shows a notifications, and worked fine until chrome updating and doesn't work any more with Chrome.
What I should edit on this code to make it working.
here is my code.
deskNoti=webkitNotifications.createNotification(chrome.app.getDetails().name,'You have '+counter+' new messages');
deskNoti.onclick=function(){openPage();this.cancel()
};
deskNoti.show();
if(timeNoti){window.setTimeout(function(){deskNoti.cancel();},timeNoti);}
webkitNotifications has been removed. The direct replacement is Notifications API.
The code is easy to translate:
// Instead of calling a create function, one calls the "new" operator:
deskNoti = new Notification(
chrome.app.getDetails().name,
// Instead of just message text, the second parameter is now an object
// with multiple properties. Message text should go into "body" parameter:
{ body: 'You have '+counter+' new messages' }
);
// Instead of .cancel(), the function to close the notification is now .close()
deskNoti.onclick = function() { openPage(); this.close() };
// Notifications are now shown automatically; there is no .show() function
//deskNoti.show();
if(timeNoti) {
window.setTimeout(function() { deskNoti.close(); }, timeNoti);
}
Consider using chrome.notifications API instead.