As with any kind of app, there are difficult issues to solve when we write Node apps. In this article, we’ll look at some solutions to common problems that we might encounter when writing Node apps.
Log Inside page.evaluate with Puppeteer
We can log output when page.evaluate
is run by listening to the console
event.
For instance, we can write:
const page = await browser.newPage();
page.on('console', consoleObj => console.log(consoleObj.text()));
We call browser.newPage
to create a new page object.
Then we listen to the console
event with it.
It takes a callback, which we can convert to text with the text
method.
Testing Asynchronous Function with Mocha
We can run async functions with Mocha tests to test them.
For instance, we can write:
it('should do something', async function() {
this.timeout(40000);
const result = await someFunction();
assert.isBelow(result, 3);
});
We call this.timeout
to set the timeout before the test times out.
Then we use await
to run our async function, which returns a promise.
Finally, we get the result and use assert
to check it.
Acknowledgment for socket.io Custom Event
We can listen to events after a connection is established.
On the server-side, we can listen to the connection
event to see if a connection is established.
Once it is, then we emit an event to acknowledge the connection is made.
Likewise, we can do the same on the client-side.
For instance, in our server-side code, we write:
io.sockets.on('connection', (sock) => {
sock.emit('connected', {
connected: 'yes'
});
sock.on('message', (data, callback) => {
console.log('received', data);
const responseData = {
hello: 'world'
};
callback(responseData);
});
});
We listen to the connection
event to listen to connections.
Then we emit the connected
event to acknowledge the connection.
We also listen to the message
event which takes data and a callback, which we call to send data back to the client.
The on the client-side, we write:
const socket = io.connect('http://localhost:3000');
socket.on('error', (err) => {
console.error(err);
});
socket.on('connected', (data) => {
console.log('connected', data);
socket.emit('message', {
payload: 'hello'
}, (responseData) => {
console.log(responseData);
});
});
We connect to the server with io.connect
.
And we listen to the error
even which runs a callback if there’s an error.
We also listen to the connected
event for any data that’s sent.
And we emit a message event with some data and a callback which the server calls to get the data we passed into the callback
function in the server-side code.
responseData
is the responseData
passed into callback
in the server-side code.
Download Large File with Node.js while Avoiding High Memory Consumption
We can make an HTTP request with the http
module.
Then we listen to the response
event, which has the downloaded file’s content.
We create a write stream with the file path.
Then we listen to the data
event emitted on the response
object to get the chunks of data.
We also listen to the end
event emitted from response
so that we can stop writing to the stream.
For example, we can write:
const http = require('http');
const fs = require('fs');
const download = (url, dest, cb) => {
const file = fs.createWriteStream(dest);
const request = http.get(url, (response) => {
response.pipe(file);
file.on('finish', () => {
file.close(cb);
});
}).on('error', (err) => {
fs.unlink(dest);
if (cb) cb(err.message);
});
};
We created a write stream with fs.createWriteStream
.
Then we make our request with the http.get
method.
We call response.pipe
to pipe the response to our write stream, which writes it to the file.
We listen to the finish
event and close the write stream in the callback.
If there’s an error, we delete what’s written so far with unlink
.
We listen to the error
event to watch for errors.
cb
is a callback that we call to deliver the results.
Since the data is obtained in chunks, memory usage shouldn’t be an issue.
Conclusion
We can download a file and write it to disk with a write stream. We can log the output with Puppeteer. Mocha can run async functions in tests. We can send events to acknowledge the emission of custom events.