Reputation: 413
I am currently trying to add 10 different values in my database through a forloop and then respond with "res 200". However it seems like res 200 runs before the loop have even started and I keep getting error "Cannot set headers after they are sent to the client" when moving it arround.
My code:
app.post("/api/v1/getWeatherData",async(req,res)=>{
let sources = await db.query("SELECT * FROM weather where element = 'mean(air_temperature P1D)' LIMIT 10;")
console.log(sources.rows)
try{
let count = 1
sources.rows.map(async(source)=>{
sleep(5000)
fetch(`https://frost.met.no/observations/v0.jsonld?sources=${source.source_id}&referencetime=${(source.valid_from).split("T")[0]}%2F2022-02-20&elements=mean(air_temperature%20P1D)&fields=value%2C%20referenceTime`, {
method: "get",
body: JSON.stringify(),
headers: {
Authorization:
"MYSECRET",
},
})
.then((res) => res.json())
.then(async tempData => {
/* tempData.data.map(async (currentWeatherData)=>{
await db.query("INSERT INTO weather_data(weather_id,element,time,value) values ($1,'mean(air_temperature P1D)',$2,$3);",[input.rows[0].weather_id,currentWeatherData.referenceTime.split("T")[0],parseInt(currentWeatherData.observations[0].value)])
}) */
console.log("completed");
count+=1
console.log("happend")
})
})
if (count >=10){
console.log(count)
res.status(200).json({
status: "success",
data: {
value: "Oppdatert",
},
});
}
}
catch(err){console.log(err)}
})```
Upvotes: 0
Views: 33
Reputation: 707298
You have to wait for the fetch()
operations to be done before your counter will be valid. The simplest way to do that is to sequence them by using await
like this:
app.post("/api/v1/getWeatherData", async (req, res) => {
try {
let sources = await db.query(
"SELECT * FROM weather where element = 'mean(air_temperature P1D)' LIMIT 10;")
let count = 1;
for (let source of sources.rows) {
await sleep(5000);
let res = await fetch(
`https://frost.met.no/observations/v0.jsonld?sources=${source.source_id}&referencetime=${(source.valid_from).split("T")[0]}%2F2022-02-20&elements=mean(air_temperature%20P1D)&fields=value%2C%20referenceTime`, {
method: "get",
headers: {
Authorization: "MYSECRET",
},
});
let tempData = await res.json();
/* tempData.data.map(async (currentWeatherData)=>{
await db.query("INSERT INTO weather_data(weather_id,element,time,value) values ($1,'mean(air_temperature P1D)',$2,$3);",[input.rows[0].weather_id,currentWeatherData.referenceTime.split("T")[0],parseInt(currentWeatherData.observations[0].value)])
}) */
console.log("completed");
count += 1
console.log("happend")
}
if (count >= 10) {
console.log(count)
res.status(200).json({
status: "success",
data: {
value: "Oppdatert",
},
});
}
} catch (err) {
console.log(err);
res.sendStatus(500);
}
});
Summary of Changes:
await
to fetch()
and to res.json()
await db.query()
body
argument from the fetch()
call as no body should be sent with the GET request.res.sendStatus(500)
to the catch handler so a response of some kind is always sent. You can obviously change that to whatever response is appropriate when there's an error, but you must send some response.await
in front of sleep(5000)
since it wasn't actually doing anything without that. Note, this means it will take 50 seconds (5 * 10) to send a response back to the client.Note:
In the case where count is not >= 10, you probably need an else
statement and send some sort of response there because all paths through this code must send some sort of http response. I'm not sure what you're trying to test for there.
If you want to and can run all the requests in parallel, you could also do that by accumulating the promises and using Promise.all()
to know when they are all done like this:
app.post("/api/v1/getWeatherData", async (req, res) => {
try {
let sources = await db.query(
"SELECT * FROM weather where element = 'mean(air_temperature P1D)' LIMIT 10;")
let count = 1;
await Promise.all(sources.rows.map(async source => {
let res = await fetch(
`https://frost.met.no/observations/v0.jsonld?sources=${source.source_id}&referencetime=${(source.valid_from).split("T")[0]}%2F2022-02-20&elements=mean(air_temperature%20P1D)&fields=value%2C%20referenceTime`, {
method: "get",
headers: {
Authorization: "MYSECRET",
},
});
let tempData = await res.json();
/* tempData.data.map(async (currentWeatherData)=>{
await db.query("INSERT INTO weather_data(weather_id,element,time,value) values ($1,'mean(air_temperature P1D)',$2,$3);",[input.rows[0].weather_id,currentWeatherData.referenceTime.split("T")[0],parseInt(currentWeatherData.observations[0].value)])
}) */
console.log("completed");
count += 1
console.log("happend")
}));
if (count >= 10) {
console.log(count)
res.status(200).json({
status: "success",
data: {
value: "Oppdatert",
},
});
}
} catch (err) {
console.log(err);
res.sendStatus(500);
}
});
Upvotes: 1