Catching an error for an async call - node.js

And then when adding a stream, I try to catch an occurring error:
try {
logger.addStream(stream); // ERROR HAPPENS AT THIS CALL
console.info(`TRY activated`);
} catch (e) {
console.error(e);
}
I do get the TRY activated message, but the app still crashes. This leads me to the thought that the async model prevents the try-catch to work here.
I added a callback to the addStream() as follows:
logger.addStream(stream, (err, stream) => {
console.log(err);
});
but this doesn't help either.
Also tried with logger.on('error', (err, stream) => { console.log(err) }); but unsuccessful as well.
I'm getting a getaddrinfo ENOTFOUNDerror:
/app/node_modules/gelf/gelf.js:95
throw err;
^
Error: getaddrinfo ENOTFOUND graylog-server
at errnoException (dns.js:28:10)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:76:26)
Can I catch that locally? F.e. without adding uncaughtException to my process, etc...

Related

Proper way to handle fetch errors in NodeJS v18?

I switched to NodeJS v18 with the built-in fetch and I'm using it as such:
async function get511AK() {
let res = await fetch(URL, { method: 'GET' })
if (res.ok && (res.headers.get('content-type').includes('json'))) {
let data = await res.json();
jsonresponseAK = data;
} else {
console.log("(" + res.url + ') is not json');
}
}
However, sometimes I'm getting a timeout on the URL, which is going to happen, but it's causing the script to exit. I've tried wrapping this in try/catch and it did not prevent it from exiting.
This never happened in Node v12 under the node-fetch library. What else can I add to control those connection timeouts?
node:internal/deps/undici/undici:11118
Error.captureStackTrace(err, this);
^
TypeError: fetch failed
at Object.fetch (node:internal/deps/undici/undici:11118:11)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Timeout.get511AK [as _onTimeout] (/home/wazebot/dot-scripts/script-relay.js:76:12) {
cause: ConnectTimeoutError: Connect Timeout Error
at onConnectTimeout (node:internal/deps/undici/undici:6625:28)
at node:internal/deps/undici/undici:6583:50
at Immediate._onImmediate (node:internal/deps/undici/undici:6614:13)
at process.processImmediate (node:internal/timers:471:21) {
code: 'UND_ERR_CONNECT_TIMEOUT'
}
}
Node.js v18.12.1
Hope it helped!
process.on('uncaughtException', console.log);
// Uncaught Exception thrown - when you throw an error and did not catch anywhere.
process.on('unhandledRejection', console.log);
// Unhandled Rejection at Promise - similar, when you fail to catch a Promise.reject.

How can I gracefully handle a failed tcpSocket.connect attempt?

The following code causes an error when there is no existing TCP server to communicate with on the specified host:
const net = require('net');
const argv = require('minimist')(process.argv.slice(2));
try {
var tcpSocket = new net.Socket();
tcpSocket.connect(argv.tcpport, argv.tcphost, function onConnected() {
console.log('connected');
tcpSocket.on('data', function onIncoming(data) {
console.log(data);
});
tcpSocket.on('close', function onClose(data) {
tcpSocketConnected = false;
});
tcpSocketConnected = true;
});
} catch (err) {
console.log("PRINT ME: ", err);
}
Error:
events.js:183
throw er; // Unhandled 'error' event
^
Error: connect ECONNREFUSED 127.0.0.1:1906
at Object._errnoException (util.js:992:11)
at _exceptionWithHostPort (util.js:1014:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1186:14)
I am unable to catch the error even though I wrap the code in a try...catch.
Why does my catch block not catch the error?
How can I gracefully handle the error?
You should be able to explicitly handle the error event using event emitter api (same way as you handled close and data):
tcpSocket.on('error', handleError)
From Docs:
Event: 'error'#
Added in: v0.1.90
<Error>
Emitted when an error occurs. Unlike net.Socket, the 'close' event
will not be emitted directly following this event unless server.close()
is manually called. See the example in discussion of server.listen().

How to test a function that throws an error asynchronously, using tape?

I am attempting to test this module (receiver.js) for an error thrown:
var request = require('request')
module.exports = function(url){
request({
url: url,
method: 'POST'
}, function(error) {
if(error){
throw error
}
})
}
using this test (test.js):
var test = require('tape')
test('Receiver test', function(t){
var receiver = require('./receiver')
t.throws(function(){
receiver('http://localhost:9999') // dummy url
}, Error, 'Should throw error with invalid URL')
t.end()
})
but tape runs the assertion before the error is thrown, resulting in the following error message:
TAP version 13
# Receiver test
not ok 1 Should throw error with invalid URL
---
operator: throws
expected: |-
[Function: Error]
actual: |-
undefined
at: Test.<anonymous> (/path/to/tape-async-error-test/test.js:5:4)
...
/path/to/receiver.js:9
throw error
^
Error: connect ECONNREFUSED 127.0.0.1:9999
at Object.exports._errnoException (util.js:856:11)
at exports._exceptionWithHostPort (util.js:879:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1062:14)
Is there a way around this?
Generally, using tape, you have to ensure you call assert.end() after the async call has completed. Using promises (would require request-promise and returning the promise):
test('Receiver test', function(t){
// Tells tape to expec a single assertion
t.plan(1);
receiver('http://localhost:9999')
.then(() => {
t.fail('request should not succeed')
})
.catch(err => {
t.ok(err, 'Got expected error');
})
.finally({
t.end();
});
});
Using async/await:
test('Receiver test', async function(t) {
try {
await receiver('http://localhost:9999');
assert.fail('Should not get here');
} catch (err) {
assert.ok(err, 'Got expected error');
}
t.end();
});
The above example is mostly correct but here's a complete working example that compares async to synchronous side by side and also shows how to check for the error message in a manner similar to the tape examples given on tape's README.md.
test('ensure async function can be tested to throw', async function(t) {
// t.throw works synchronously
function normalThrower() {
throw(new Error('an artificial synchronous error'));
};
t.throws(function () { normalThrower() }, /artificial/, 'should be able to test that a normal function throws an artificial error');
// you have to do this for async functions, you can't just insert async into t.throws
async function asyncThrower() {
throw(new Error('an artificial asynchronous error'));
};
try {
await asyncThrower();
t.fail('async thrower did not throw');
} catch (e) {
t.match(e.message,/asynchronous/, 'asynchronous error was thrown');
};
});

ECONNREFUSED in Node http module

When a remote site is off-line I am getting this error in my consuming client (Node.js v0.12.0 with the http module):
Uncaught exception: connect ECONNREFUSED
Error: connect ECONNREFUSED
at exports._errnoException (util.js:746:11)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:983:19)
The code I'm currently using looks like this:
var req = http.request(options, function (res) {
res.on('socket', function (socket) {
socket.setKeepAlive(true, 0);
socket.setNoDelay(true);
});
res.on('end', function () {
log.debug('Success');
}).on('error', function () {
log.error('Response parsing failed');
});
}).on('error', function () {
log.error('HTTP request failed');
});
req.write(packet);
req.end();
The "error" event is never fired when the ECONNREFUSED occurs, I've tried using the "clientError" event but this is not fired either.
How can I capture this error?
Extracted from: https://stackoverflow.com/a/4328705/4478897
NOTE: This post is a bit old
The next example is with the http.createClient but i think it could be the same
Unfortunately, at the moment there's no way to catch these exceptions directly, since all the stuff happens asynchronously in the background.
All you can do is to catch the uncaughtException's on your own:
process.on('uncaughtException', function (err) {
console.log(err);
});
Maybe that helps you!
More this: https://stackoverflow.com/a/19793797/4478897
UPDATE:
did you tried to change log.error() to console.error() ???

Reconnect to TCP/IP socket on NodeJS

I use "net" library to create TCP connection on my nodeJs.
root.socket = net.createConnection(root.config.port, root.config.server);
I'm trying to handle error when remote server is down and reconnect in Cycle.
root.socket.on('error', function(error) {
console.log('socket error ' + error);
root.reconnectId = setInterval(function () {
root.socket.destroy();
try {
console.log('trying to reconnect');
root.socket = net.createConnection(root.config.port, root.config.server);
} catch (err) {
console.log('ERROR trying to reconnect', err);
}
}, 200);
}
The trouble is that in case of remote server shutdown I still get en error and my nodeJS server stops.
events.js:72
throw er; // Unhandled 'error' event
^ Error: connect ECONNREFUSED
at errnoException (net.js:904:11)
at Object.afterConnect [as oncomplete] (net.js:895:19)
You will need something like this:
var net = require('net');
var c = createConnection(/* port, server */);
function createConnection(port, server) {
c = net.createConnection(port, server);
console.log('new connection');
c.on('error', function (error) {
console.log('error, trying again');
c = createConnection(port, server);
});
return c;
}
In your case you are creating a new connection but you don't attach any error listener, the error is raised somewhere else in the execution loop and can not be caught by the "try / catch" statement.
P.S. try to avoid using "try / catch" statement, error handling in Node.JS is made using error listeners and domains, it can be useful only for JSON.parse() or other functions that are executed synchronously.

Resources