Why is my catch statement triggering even though the .then is resolved? - javascript

This is the code I have currently in my server folder. I was just wondering for some reason the catch console log is still sending even though the .then statement actively sends a response though res.send works and sends a response to the user?
const express = require("express");
const router = express.Router();
const { API_KEY, API_URL } = process.env
const axios = require("axios")
router.get("/", async (req, res) => {
console.log(API_URL + API_KEY)
await axios.get(API_URL + API_KEY + "&count=9")
.then((response) => {
res.send(response.data)
})
.catch(
console.log("error")
)
})
module.exports = router
Thank you!

.catch accepts a callback - right now, you're invoking console.log immediately and passing the result to .catch. This:
// ...
.catch(console.log("error"))
is equivalent to
const consoleResult = console.log("error");
// ...
.catch(consoleResult)
You need to change to
.catch(
() => {
console.log("error")
}
)
Or, even better, examine the argument to see what the error was:
.catch(
(error) => {
console.log("error:", error.message)
}
)

Related

res.json is not sending my error message to the client?

I have this error handler that retreives specific error messages based on what happens. But the thing is when I run my error handler function with .catch() it will work if i'm logging to the node console, but when i try send it to the client via res.json() it will only send the status code, not any part of my error handler.
function errorHandler(error){
if (error.name === 'SequelizeValidationError') {
const errors = error.errors.map(err => err.message);
return errors;
} else {
throw error;
}
}
router.post('/create', async(req, res) => {
await Movie.create(req.body)
.then(() => res.json("Movie Created"))
.catch( err => res.status(401).json(errorHandler(err)) );
});
This is my code for the error handler and the route i'm talking about. It works in the node console, but like I said it only sends the status 401 code to the client and nothing else. How can I get my error message send to the client as well?
Thank you!
Because its not waiting for result from errorHandler. Make them wait for it.
Try this.
function errorHandler(error, cb){
if (error.name === 'SequelizeValidationError') {
const errors = error.errors.map(err => err.message);
cb(errors);
} else {
throw error;
}
}
router.post('/create', async(req, res) => {
await Movie.create(req.body)
.then(() => res.json("Movie Created"))
.catch( err => {
errorHandler(err, function(errors){
res.status(401).json(errors);
});
});
})
Or you can return a Promise and await on errorHandler.

How to handle error without crashing function with axios?

So the problem is, that in some function i want to call getRecord function. It's making request with axios. Some times request can be faild, so i want to handle the error without crashing my function, where i'm calling getRecord.
I'm calling getRecord like this:
const res = await getRecord(eventData)
console.log('handleReadyToRemoveCalls -> res', res)
Here is the getRecord function
const getRecord = ({ extTrackingId, targetId }) => {
console.log('getRecord -> executed')
const apiConfig = require('../config')
return new Promise((resolve, reject) => {
axios({
method: 'get',
url: `https://cloudpbx.beeline.ru/apis/portal/v2/records/${extTrackingId}/${targetId}/download`,
responseType: 'stream',
headers: {
'X-MPBX-API-AUTH-TOKEN': `${apiConfig.token}`,
},
})
.then((response) => {
console.log('getRecordsReference -> response', response)
resolve(response)
})
.catch((err) => {
console.log('getRecordsReference -> err', err)
reject(err)
})
})
}
With this approach i'm suddenly for me getting crashes, when request with axios fails. What's i'm doing wrong?
You are rejecting the promise in the catch block:
.catch((err) => {
reject(err)
})
Thus your propagate the error. If you want the function not to fail just return something that is not an error like an empty array. For instance:
.catch((err) => {
resolve([])
})
One other way to handle this is to reject as you do and to catch the error higher with a try catch like this:
try {
const res = await getRecord(eventData)
} catch(err){
// do whatever you want in case of an error
}
Surround with try catch.
try{
const res = await getRecord(eventData)
}catch(err){
//say dispatch a function and say please try again in UI
}
In you promise you are rejecting the with an error. That error needs to be handled in the block you are calling the function.

Fetch Delete Request not working Properly

With the Fetch API I am sending the following request:
const target = e.currentTarget;
fetch(target.href, {
method: 'delete',
})
.then(res => console.log(22))
.catch(err => console.log(err));
Also, this is the middleware that handles this request:
exports.deleteImageById = async (req, res) => {
const image_id = req.params.image_id;
const imagePromise = Image.findByIdAndRemove(image_id);
const commentPromise = Comment.remove( {image_id} );
await Promise.all([imagePromise, commentPromise])
.catch(err => console.log(err));
req.flash('Image Deleted!');
// return something well!
res.status(200);
};
The document is being deleted but the then block in the fetch statement does not work. It does not output anything to the console.
Am I doing something wrong here?
The response is not being received and therefore the then will not be called. In the server change
res.status(200);
to include end() since status does not send the response
res.status(200).end();
or sendStatus
res.sendStatus(200);
res.status is only used to set the status code it does not send the response.
Instead use the following:
res.sendStatus(200)

Async http-request, node.js modules and variables

I'm currently struggling to get variable values from one node.js module into another. This is my current problem:
I am fetching data from a REST API via https-request:
// customrequest.js
sendRequest( url, function( data, err ) {
if(err) {
console.log('--- Error ---');
console.log( err );
}
else {
console.log('--- Response ---');
console.log(data);
// output: data
return data;
}
module.exports = { sendRequest }
And my index.js file:
// index.js
let sendRequest = require('./customrequest');
let req;
req = sendRequest('google.com');
console.log(req);
// output: undefined
// how can I get the variable set, when request is getting data in response?
I totally understand, that the request to an API takes some time for the response. One solution is, that I just put everything into one js file. But as my project will get bigger over time, the modular approach is my goto-solution. Any suggestions on how to solve this?
Node uses callbacks for this situation. Try something like this:
// customrequest.js
sendRequest(url, callback)
module.exports = { sendRequest }
// index.js
let sendRequest = require('./customrequest');
let req = sendRequest('google.com', function (data, err) {
if (err) {
//handle error here
}
console.log(data);
};
// output: undefined
// how can I get the variable set, when request is getting data in response?
Thanks. The problem I encounter is somewhat different. I solved it with this code snippets … using async and await.
// request.js
const fetch = require('node-fetch')
async function myRequest (somestring) {
try {
let res = await fetch('https://api.domain.com/?endpoint='+somestring)
if (res.ok) {
if (res.ok) return res.json()
return new Error (res.status)
}
} catch (err) {
console.error('An error occurred', err)
}
}
module.exports = { myRequest }
// index.js
const request = require('./requests')
const myRequest = request.myRequest
let myVar;
myRequest('somestring')
.then(res => myVar = res.result)
setInterval(() => {
myRequest('somestring')
.then(res => myVar = res.result)
console.log(myVar)
}, 1000)
The async function and awaits return a promise. This promise is, when resolved, assigned to a variable.

How to set default rejected promise behavior for all my Express middlewares?

I'm using promises inside express middleware. I want to use the async/await methods.
app.get('/data1',async function(req,res) {
data = await getData1(); // This line throw an error,
res.send(data)
})
app.get('/data2',async function(req,res) {
data = await getData2(); // This line throw an error
res.send(data)
})
This makes the browser wait forever.
On the server I see
(node:251960) UnhandledPromiseRejectionWarning: Unhandled promise rejection
Now, to fix it for one middleware I'm doing:
app.get('/data1',async function (req,res){
return (async function(){
data = await getData1()
})().catch(() => {
res.send("You have an error")
}
})
app.get('/data2',async function (req,res){
return (async function(){
data = await getData2()
})().catch(() => {
res.send("You have an error")
}
})
I don't like this repetion. How can I set default error? I have tried for example:
app.use(function(error,req,res,next)){
res.send('You have an error')
}
But it didn't work.
In other words: How to set default function to be called when Express middlewares returning a rejected promise?
Now I found a way how to do it, I'm still keep the question open for more suggestions
app.get("/data1",
wrap_middleware(async (req, res) => {
data1=await getData1()
res.send(data1)
})
}
app.get("/data1",
wrap_middleware(async (req, res) => {
data2=await getData2()
})
}
function wrap_middleware(func) {
return async (req, res, next) => {
func(req, res, next).catch(err => {
console.log(err.message);
res.send("Error");
});
};
}
I don't understand the use of sending the same error for different function but I think the handling error code could be write in more readable way (just catch the error and do with them what you want the same way you catch errors in any route middleware):
function getData1(){
return new Promise( (resolve,reject) => {
setTimeout(() =>{
reject(new Error('error has occur!'));
},2000);
});
}
router.get('/data1', async (req,res, next) => {
try{
const data = await getData1();
res.send(data);
}
catch(ex){
res.send(ex.message);
// next(ex); => sending it to express to handle it
}
});
If you want a global error handling then its not any different from any code you want catch errors globally - you can set a function that take as param , the response object and the async code and create general catch for every async call comes from middleware (which has response object)

Categories