Axios Post is not completing every time - javascript

Iam new to React and I got some problems.
This is my current API call.
Axios.post(Addr_currentRound_addOne, { gameId: gameId }).then(history.push("/leiter_tunierplan/"+gameId));
And this is the corresponding API Code snippet.
app.post("/currentRoundAddOne", (req, res) => {
const gameId = req.body.gameId;
db.query(
"UPDATE tunierplan SET currentRound=currentRound+1 WHERE id=?;",
[gameId],
(err, result) => {
if (err) {
console.log(err);
} else {
res.send("Daten Übertragen");
}
}
);
});
The problem here:
currentRound, should allways when the call is executed increased by +1.
And then Redirect to the given "/leiter_tunierplan/"
BUT
From time to time, it does not work. Its not increasing it by any Value (+1)
My first thought is: Because its async it my be canceled from the history.push, befor it got completed. Am i right? And how can i fix it.
Thanks allready.

Is game gameId the already incremented id for the next page? I don't see it being incremented anywhere in your code.
If so, try putting history.push in a callback, like this:
...then(() => history.push("/leiter_tunierplan/"+gameId));
This is because then takes a callback function as a parameter

The Solution to all is to add preventDefault();
My Problem was, that the side got reloaded..

I think you try async-await as the request to the database is promise-based.
My suggestion:
app.post("/currentRoundAddOne", async (req, res) => {
const gameId = req.body.gameId
const data = await db.query("UPDATE tunierplan SET currentRound=currentRound+1 WHERE id=?;", [gameId],
(err, result) => {
if (err) console.log(err);
}
console.log(data) // check updated data, it should return id
})
I hope it works!

Related

filled array is empty when send back to user

I try to get data from an azure database with SQL and for this I use tedious. When I execute the code, the array "result" gets filled up with data but when de respond sends the array "result" to the user it is empty. Why and how can I solve it? (I want to send it back in JSON format, the legth is unknown I use 5 to debug).
This is my code
router.get('/', async (req, res) => {
result = []
let rowData = {}
const request = new Request(
`SELECT TOP (5) [LogID]
,[OpdrachtID]
,[ChangeLog]
,[TimeStamp]
,[PersonID]
FROM [log].[LOpdracht]`,
function (err, rowCount, rows) {
if (err) throw err
})
connection.execSql(request)
request.on('row', function(columns){
rowData = {}
columns.forEach(function(column){
rowData[column.metadata.colName] = column.value
})
result.push(rowData)
})
res.send(result)
})
Looks like you are using Tedious. If that is so then you can use the 'done' event to be notified when the request has completed and all rows have been read into result.
request.on('done', () => res.send(result));
Update: As the note in the documentation points out, since you are using execSql you will need to listen to doneProc and doneInProc instead:
request.on('doneProc', () => res.send(result));
request.on('doneInProc', () => res.send(result));
I solved it by adding this:
request.on('requestCompleted', () => {
res.send(result)
})

Node: run 2 sql queries at the same time

I have a simple api to communicate with my mobile app and i have some updates to do.
I want to make 2 updates at the same function (or th same route) but i dont know if its possible.
Here is the dboperation part:
async function updateCusto() {
try {
let pool = await sql.connect(config);
let updateCusto = await pool.request()
.input('input_parameter1', sql.Int, CodOS)
.input('input_parameter2', sql.Int, CodProduto)
.query("update osproduto set custounit=produto.precocusto, valorunitario=produto.precosugerido from OSProduto INNER JOIN Produto ON OSProduto.CodProduto = Produto.Codigo where codproduto=#input_parameter2 and codos=#input_parameter1")
.query("Update OSProduto set sub=qtde*valorunitario where codos=#input_parameter1") //the second one, doenst work
return updateCusto.recordsets;
}
catch (error) {
console.log(error);
throw error;
}
}
and here is the route part:
router.route("/updateCusto").post((request, response) => {
CodOS = request.body.CodOs;
CodProduto = request.body.CodProduto;
dboperations.updateCusto(CodOS, CodProduto).then(result => {
console.log(result);
response.json("Update ok!");
})
.catch(error => response.json({ error }))
})
How can i do this? Is there a way to run the 2 updates on the same operation? Or do i need to create another operation to use on the same route, after the first update is made (and if so, how can i do that?).
It's definitely possible, in fact I would do it as a transaction, this way if one of the queries fails a rollback would be made in order to preserve the state of your database.
Here are my suggestions:
Read about database transactions
Replace pure SQL with an ORM such as Sequelize or KnexJS, it will help you to prevent errors by making queries calling methods such as await OsProduto.update({ where: { id: 0 }}, newData);

Request inside a nested request loop to another server

I need to request X products from another server and I need to wait for that execution to finish before proceeding and saving the order in the database.
Let's say I receive via post an array of product Ids that I need to add to the order, e.g
JSON FILE:
{
"order_products":[1,2,3,4]
}
Here's a code sample:
//Express module
var router = require('express').Router();
//HTTP Request module
var client = require('request');
//Util that saves the URLs of the other databases
var productURL = require('../utils/product/productURL');
//Builds a product object given a JSON
var productBuilder = require('../utils/product/productBuilder');
router.post('/', req, res) {
//Instantiate a new order
var orderInstance = new order({
date: Date.now
});
//Query the products in the other server and add them to the order
req.body.order_products.forEach(id => {
client.get(productURL.HTTPS + id, { json: true }, (err, res, JSONProduct) => {
var product = productBuilder.build(JSONProduct);
orderInstance.order_products.push(product);
});
};
//Save the order in the database
orderInstance.save(....);
//Send response
res.status(201).json(orderInstance);
}
The problem here is that while the loop is still executing, the response is sent (201) and the orderInstance is saved without any product. If I console.log the products they only appear after the orderInstance is saved.
I've tried implementing callbacks to fix this issue, but with no success. I'd appreciate if anyone could lend me a hand here! Thanks in advance :smiley:(edited)
forEach runs synchronously - when the forEach ends, the client.get requests may have all been sent out, but the responses surely haven't come back yet. You need to convert each request into a Promise, and then call Promise.all on an array of those Promises. The Promise.all will resolve once all responses have come back. For example:
const allPromises = req.body.order_products.map(id => new Promise((resolve, reject) => {
client.get('productURL.HTTPS' + id, { json: true }, (err, res, JSONProduct) => {
if (err) reject (err);
else resolve(productBuilder.build(JSONProduct));
});
}));
Promise.all(allPromises)
.then((newProducts) => {
orderInstance.order_products.push(...newProducts);
res.status(201).json(orderInstance);
})
.catch((err) => {
// handle errors
});

Increment field user.entries when I hit submit

any idea how to increment a field called 'entries' by 1 every time I hit the submit button and save it to the database (I am using MongoDB/mongoose)?
app.put('/image', (req, res) => {
const { id } = req.body;
User.findByIdAndUpdate(id)
.then(user => {
return res.json(user.entries);
})
.catch(err => {
res.status(400).json('Error getting entries');
console.log(err);
})
});
I tried the auto-incremet plugin, but I don't know if it works in this case, if so I couldn't quite place it in the right place. I also tried to add like
User.findByIdAndUpdate(id, {$inc: {'entries': 1}} but it only starts to work when I hit the but twice and on.
If anyone can help me It'd be a great help!! Thanks
It is working. The only reason is that, findByIdAndUpdate returns the document before actually performing the update operation. If you want to get the increment value after the update operation, You might want to split the findByIdAndUpdate and try
User.update({_id: id},{$inc: {'entries': 1}}).then(() => {
User.findOne({_id: id}).then( user =>{
return res.json(user.entries);
})
}).catch(err => {
res.status(400).json('Error getting entries');
console.log(err);
})
You could also check this solution out by #Jonathan Lonowski if you still want to go with the findByIdAndUpdate.

Nodejs variable prints on console but not on the view

the code is this
module.exports = {
index: function (req, res, next) {
//get an array of all users in user collection
Notification.find(function foundNotification(err, notifications) {
if (err) return next(err);
var elusuario=[];
User.findOne(2, function foundUser (err, user) {
if (err) return next(err);
if (!user) return next();
console.log(user);
console.log("----------------------------");
elusuario = user;
console.log(elusuario);
});
res.view({
notifications: notifications,
elusuario: elusuario
});
})
}
};
That is the controller and in the console prints elusuario good but in the view the user hasn't values. why?
i think is something is something related to the globals variables. but i dont know
thanks
EDIT
all right so the method is async. what im trying to do is find the notifications and the user by her user.id and get the user.name so what if i do this
module.exports = {
index: function (req, res, next) {
//get an array of all users in user collection
Notification.find(function foundNotification(err, notifications) {
if (err) return next(err);
User.find(function foundUser (err, users) {
if (err) return next(err);
var usuarios_locotes = [];
_.each(notifications, function (notification) {
_.each(users, function (user) {
if(notification.token_user==user.token){
console.log(user.token);
usuarios_locotes.push(user);
console.log(usuarios_locotes);
};
});
});
res.view({
notifications: notifications,
users: usuarios_locotes
});
});
})
}
};
it still not working? the __.each is an async funtion to?
sorry for all this maybe stupid questions
The method findOne of User object runs asynchronously. Because of this, you are rendering the view before the findOne returns the user object.
If you put a console.log before the render.view, it'll print the output before the console.log inner findOne method.
When the code is running, the function foundNotification is not executed before you call the res.view. My advice for you is read about Promises.
You can change your code as below to work:
function (req, res, next) {
//get an array of all users in user collection
Notification.find(function foundNotification(err, notifications) {
if (err) return next(err);
var elusuario=[];
User.findOne(2, function foundUser (err, user) {
if (err) return next(err);
if (!user) return next();
console.log(user);
console.log("----------------------------");
elusuario = user;
console.log(elusuario);
res.view({
notifications: notifications,
elusuario: elusuario
});
});
});
}
the findOne Method is an asynchrone method,so it's executed without provinding the res.view with the appropriate data
try to wrap the whole logic in the same function, it may look ugly but it ll do the thing for now
All right so.. first really thanks to everybody. I solve this shit.
I know this is not the right way to do this but it works, so for my proposes it's fine.
the problem after the EDIT was that in the view I'm trying to write an object with parameters but what I've was sending was vector of vector so changing this line:
usuarios_locotes.push(new Object(users[h]));
I can send a vector of objects.
So.. anyway thanks cause later i will change my code to do it better and efficient
This was my first post so sorry for not read the first steps of how to use this haha cause i think i have been make a lot of mistakes.
And sorry for my English :C

Categories

Resources