Fetch Delete Request not working Properly - javascript

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)

Related

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

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)
}
)

Can anyone explain why my program is not showing the correct alert?

I have written this function which allows users to add images to the server. However, my alerts don't seem to be working. I've tried to console.log the alert messages instead of having them as alerts but that doesn't seem to work either. Any tips would be great.
client.js
async function picsub(event){
event.preventDefault();
var image=document.getElementById('imageFile');
const formData = new FormData();;
formData.append('image',image.files[0]);
let i={
method:'POST',
body:formData,
}
fetch('http://127.0.0.1:8090/pics', i).then((response) => {
return response.text();
}).then((response) => {
if (response === 'success') {
alert('pic added');
} else {
alert('An error has occurred');
}
}).catch((e) => {
alert('An error has occurred');
form.reset();
}
const form = document.getElementById("form");
form.addEventListener("submit", picsub);
server.js
const app = express();
const port = 8090;
let pictures=[];
app.post('/pics', (req, res) => {
const pic = req.body;
console.log(pic);
pictures.push(pic);
res.status(201);
});
In your express, you only setup the status, but you didn't send any message from server. So, your then or catch in fetch will be executed.
then will be executed when you receive the response from server.
catch will be executed when you have failed connection between client and server.
In your case, you didn't send any response from server, fetch function will wait for response until timeout. But, you didn't setup any timeout. That means there are no response from server or any failed connection. So, your then or catch in fetch will not be executed. Unless, you shut down the server. But, browser will help you setup the default timeout, such as Chrome. It use 300 seconds as timeout.
So, you need to send message with res.end("success") like below.
app.get('/pics', function (req, res) {
const pic = req.body;
console.log(pic);
pictures.push(pic);
res.status(201).end("success");
})
And in your client.js, you should complete the bracket in the fetch function.
fetch('http://127.0.0.1:8090/pics', i).then((response) => {
return response.text();
}).then((response) => {
if (response === 'success') {
alert('pic added');
} else {
alert('An error has occurred');
}
}).catch((e) => {
alert('An error has occurred');
}) // ===> here
Try not using async here. Also, try console.log() some things within the function, especially near the alert(). This way, you know it even gets to the alert()

How to call an external API then return this data from an in hapi.js Api

I am new to the Hapi.js node extension.
I am trying to call an external API into my server because the external API is protected with CORS and I can't call it from my front (Angular 9).
So I set up my hapi server with routes etc and now in a route I am trying to import the external data and when the front call the route of my hapi api it show the data from the external API.
I didn't find any documentation or already topics about this problem, if you could provide me with some information it would be very helpful!
(I want to do my external API call from the route solcast)
This is my index.js :
'use strict';
require('dotenv').config()
const Hapi = require('#hapi/hapi');
const init = async () => {
const server = Hapi.server({
port: 3000,
host: 'localhost',
routes: {
cors: true
}
});
server.route(require('./routes/base').test);
server.route(require('./routes/solcast').solcast);
await server.start();
console.log('Server running on %s', server.info.uri);
};
process.on('unhandledRejection', (err) => {
console.log(err);
process.exit(1);
});
init();
This is my solcast.js :
This while console.log the error :
Error: handler method did not return a value, a promise, or throw an error
And then console.log the data. I assume that the data is not received when the return is done.
const joi = require('#hapi/joi');
const fetch = require("node-fetch");
exports.solcast = {
method: 'GET',
path: '/solcasttest',
handler: (request, h) => {
fetch("https://linkToTheExternalApi")
.then(response => response.json())
.then(data => {
console.log(data)
return data
})
.catch(err => console.log(err))
console.log(testSolcast)
}
}
Thank you for your help, if you need any other information hit me up.
As the error thrown suggests, a handler in hapi.js must return a value, a promise or throw an error.
In your case, the handler is an asynchronous operation, so you have to return a promise.
As fetch already creates a promise, it is enough if you return the promise created by fetch in your handler :
const fetch = require("node-fetch");
exports.solcast = {
method: 'GET',
path: '/solcasttest',
handler: (request, h) => {
return fetch("https://linkToTheExternalApi")
.then(response => response.json())
.then(data => {
console.log(data)
return data
})
.catch(err => console.log(err));
}
}

EJS using fetched json data with d3 chart

*New to express.
I have index.ejs and script.js.
My script fetches some JSON data from an api just fine.
const fetch = require("node-fetch");
const url = '...'
fetch (url)
.then(response => {
return response.json()
})
.then(data =>{
console.log(data)
})
.catch(err => {
})
How would I go about using this returned JSON data to create a chart in my index page with d3.
I have searched around but am still confused. Any advice would be super helpful! Thanks.
So as discussed in the comments, the problem was having a server which is return in express framework of nodejs
So in express code need to call an api and get data, once we get the data we need to send it to the front end.
So for returning data to front end we can use res.send of express
const fetch = require("node-fetch");
const url = '...'
fetch (url)
.then(response => {
return response.json()
})
.then(data =>{
console.log(data)
res.send(data)
})
.catch(err => {
})
And in the front end we need to access this api as shown below
const getData = async () => {
try {
const response = await fetch(url) // server url (express js route) example http://localhost:6000/api/getChartData
if(response.ok){
const body = await response.json()
console.log(body)
// once you get the data you can create d3 chart
return
}
const customError = {
message: 'something went wrong'
}
throw customError
}catch(error){
console.log(error)
// put the error in a variable and display on the ui so the user know some error happened
}
}

How catch error in the front-end from response of expressjs?

My problem is the next:
//express server
app.post('/register', (req, res) => {
const {
password,
passwordConfirm
} = req.body;
if (password === passwordConfirm) {
//...
} else {
res.status(400).json("Passwords aren't matching")
}
})
//react function
onSubmitSignIn = () => {
const { password, passwordConfirm } = this.state;
let data = new FormData();
data.append('password', password);
data.append('passwordConfirm', passwordConfirm);
fetch('http://localhost:3001/register', {
method: 'post',
body: data
})
.then(response => response.json())
.then(user => {
//logs error message here
console.log(user)
})
//but I want to catch it here, and set the message to the state
.catch(alert => this.setState({alert}))
}
When I send the status code, and the message from express as the response, the front-end obviously recognize it as the response, that's why it logs the message to the console as "user". But how to send error which goes to the catch function?
fetch will really only error if it for some reason can't reason the API. In other words it will error on network errors. It will not explicitly error for non 2XX status codes.
You need to check the ok property as described here:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful
https://developer.mozilla.org/en-US/docs/Web/API/Response/ok
--
fetch('http://localhost:3001/register', {
method: 'post',
body: data
})
.then(response => {
if (!response.ok) {
throw new Error('my api returned an error')
}
return response.json()
})
.then(user => {
console.log(user)
})
.catch(alert => this.setState({alert}))
The problem is, that fetch is not recognizing the HTTP errors as Promise rejections.
The Promise returned from fetch() won't reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally, and it will only reject on network failure or if anything prevented the request from completing.
(Source)
You can checkout the linked source of the fetch repo which also states a suggestion for handling HTTP error statuses.
What if you throw an error :
app.get("/", function (req, res) {
throw new Error("BROKEN"); // Express will catch this on its own.
});
And then catch this error in the front end ?
See here for reference
EDIT
Maybe should you return the error with return next() so that the rest of the code is not processed in the server method :
app.get("/", function (req, res) {
return next(new Error('BROKEN'));
});
//express server
app.post('/register', (req, res) => {
try {
const {
password,
passwordConfirm
} = req.body;
if (password === passwordConfirm) {
//...
} else {
res.status(400).json("Passwords aren't matching")
}
} catch (error) {
res.status(500).send(error);
}
})
//react function
onSubmitSignIn = () => {
const {
password,
passwordConfirm
} = this.state;
let data = new FormData();
data.append('password', password);
data.append('passwordConfirm', passwordConfirm);
fetch('http://localhost:3001/register', {
method: 'post',
body: data
})
.then(response => response.json())
.then(user => {
//logs error message here
console.log(user)
})
//but I want to catch it here, and set the message to the state
.catch(alert => this.setState({
alert
}))
}

Categories