KeystoneJS save() inside getUpdateHandler callback doesn't work - keystonejs

I have this code on API:
var data = (req.method == 'POST') ? req.body : req.query;
if (!data.betId || !data.userId) return res.apiError('wrong request payload');
BetUser.model.findOne({bet: data.betId, user: data.userId}).exec(function(err, bets){
if (bets){
return res.apiError('you placed the bet for this bet', bets);
}
var bet_item;
item = new BetUser.model({bet: data.betId, user: data.userId});
item.getUpdateHandler(req).process(data, function(err) {
if (err) return res.apiError('error', err);
Bet.model.findById(data.betId).exec(function(err, bet){
if (err) return res.apiError('database error', err);
switch(parseInt(item.betChoice)){
case 0:
bet.drawTeamBets +=1;
break;
case 1:
bet.firstTeamBets +=1;
break;
case 2:
bet.secondTeamBets +=1;
break;
};
bet.drawTeamBets = 1000;
console.log(bet);
bet.save();
console.log(bet);
bet_item = bet;
});
User.model.findById(data.userId).exec(function(err, user){
if (err) return res.apiError('database error', err);
user.gold -= item.betAmount;
user.save();
res.apiResponse({
bet_detail : item,
user : user,
bet : bet_item
});
});
});
});
The thing is that the Bet object wasn't updated, those 2 console.log print the old object.
How can i save the bet in this case? meanwhile the User object was updated. So strange.

I think you must define a function to be called after the save operation, there are two ways to do that, first one:
bet.save(function (err, bet) {
if (err){ console.log(err); }
console.log('saved bet: ', bet);
// place for other code after save operation..
});
Using returned Promise:
bet.save().then(function (bet) {
console.log('saved bet: ', bet);
// place for other code after save operation..
});
for more details and examples: mongoosejs.com/docs/api.html#model_Model-save

Try this...
Bet.model.findById(data.betId).exec(function(err, bet){
if (err) return res.apiError('database error', err);
switch(parseInt(item.betChoice)){
case 0:
bet.drawTeamBets +=1;
break;
case 1:
bet.firstTeamBets +=1;
break;
case 2:
bet.secondTeamBets +=1;
break;
};
bet.drawTeamBets = 1000;
console.log(bet);
bet.save();
console.log(bet);
bet_item = bet;
User.model.findById(data.userId).exec(function(err, user){
if (err) return res.apiError('database error', err);
user.gold -= item.betAmount;
user.save();
res.apiResponse({
bet_detail : item,
user : user,
bet : bet_item
});
});
});
Nest your last mongoose query in the callback of the previous query. This will ensure the .save fires before the last query.

Related

How can I refresh datatable in Wire using refreshApex

#wire(_getContacts,{recordId:'$recordId'}) wiredContacts({error,data}){
this.dataToRefresh = data;
if (data) {
this.contacts = this.dataToRefresh.recordList;
this.ContactsRecords = this.dataToRefresh.cList;
this.contactsSize = " Case Contacts (" + this.contacts.length + ")";
}else{
//
}
};
relateContacts() {
this.showSpinner = true;
this.showtable=false;
relateContacts({contacts: this.selected, recordId: this.recordId})
.then(data => {
this.showSpinner=false;
this.showtable=true;
this.showSuccessMessage();
refreshApex(this.dataToRefresh);
//location.reload();
this.isShowModal = false;
})
.catch(error => {
console.log(error);
this.showSpinner=false;
const evt = new ShowToastEvent({
title: 'Application Error',
message: error.body.message,
variant: 'error',
mode: 'sticky'
});
this.dispatchEvent(evt);
this.showSpinner = false;
});
}
For this code, I tried refreshApex with all possible ways. but I'm not sure the miss here. I've Checked all the blogs but everywhere, the solution is mentioned.
Tried refreshApex like below :
#wire(_getContacts,{recordId:'$recordId'}) wiredContacts({data}){
this.dataToRefresh = data;
But this also does not work
Ah that is a fun one ! Your issue is using destructuring in wiredContacts as the parameter.
(The {data} or {data,error} normally works as a parameter to the function being called back, except if you have to do refresh) Try this instead.
#wire(_getContacts,{recordId:'$recordId'}) wiredContacts(value){
this.dataToRefresh = value;
const {data, error} = value;
//Rest of you code now with data and error
}
Then in your other method you can do:
method(){
refreshApex(this.dataToRefresh);
}
Salesforce does show doing this in their example code, but it’s easy to miss and experience the fun you have been having with this.
https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.apex_result_caching
See the last example on their page.

Syntax required for conditional variable use to modify SQL query in Node.JS

I've fairly new to NodeJS, and I'm not sure of the best method or syntax to create an MS SQL query with conditional code. Here's what I want to do, with the query greatly simplified, and using some pseudocode:
// #route GET /api/flow/data/references
async function getDataReferences(req, res) {
const { station, type } = req.query
let pool
try {
pool = await sql.connect(config)
const { recordset } = await pool
.request()
.input('station', sql.NVarChar(50), station).query`
SELECT Reference
FROM TABLE
WHERE Status = 'Done' ` +
if(type === 1) {
`AND Station_1 = #station`
} else if(type === 2) {
`AND Station_2 = #station`
} else {
`AND Station_3 = #station`
}
+ `AND Process = 5`
const processedData = recordset.map((item) => item.Reference)
res.json(processedData)
} catch (error) {
console.log(
`ERROR with Station: ${station} with Type: ${type}`,
error.message,
new Date()
)
res.status(500).json({ message: error.message })
} finally {
await pool.close()
}
}
Depending on the value of "type" supplied to the function, I want the query to reference a different DB column.
UPDATE:
So I've found that the following works, although arguably the formatting isn't quite as nice.
// #route GET /api/flow/data/references
async function getDataReferences(req, res) {
const { station, type } = req.query
let station_column
if(type === 1) {
station_column = 'AND Station_1 = #station'
} else if(type === 2) {
station_column = 'AND Station_2 = #station'
} else {
station_column = 'AND Station_3 = #station'
}
let query = `
SELECT Reference
FROM TABLE
WHERE Status = 'Done'
${station_column}
AND Process = 5`
let pool
try {
pool = await sql.connect(config)
const { recordset } = await pool
.request()
.input('station', sql.NVarChar(50), station).query(query)
const processedData = recordset.map((item) => item.Reference)
res.json(processedData)
} catch (error) {
console.log(
`ERROR with Station: ${station} with Type: ${type}`,
error.message,
new Date()
)
res.status(500).json({ message: error.message })
} finally {
await pool.close()
}
}
I tried just using the template literal substitutions directly in the query, but that wouldn't work. (Perhaps for reasons stated here: https://github.com/tediousjs/node-mssql#es6-tagged-template-literals )
If I don't get any better answer, I'll post this as the answer; but would like to know if there's a best practice method for doing this.
Seems like this works, and isn't overly complicated:
// #route GET /api/flow/data/references
async function getDataReferences(req, res) {
const { station, type } = req.query
let station_column
if(type === 1) {
station_column = 'AND Station_1 = #station'
} else if(type === 2) {
station_column = 'AND Station_2 = #station'
} else {
station_column = 'AND Station_3 = #station'
}
let query = `
SELECT Reference
FROM TABLE
WHERE Status = 'Done'
${station_column}
AND Process = 5`
let pool
try {
pool = await sql.connect(config)
const { recordset } = await pool
.request()
.input('station', sql.NVarChar(50), station).query(query)
const processedData = recordset.map((item) => item.Reference)
res.json(processedData)
} catch (error) {
console.log(
`ERROR with Station: ${station} with Type: ${type}`,
error.message,
new Date()
)
res.status(500).json({ message: error.message })
} finally {
await pool.close()
}
}
Essentially, create the full query string in advance, including the parameters to bind, and then pull that whole string in as the query.

How to stop Promise.all loop when it rejects

I'm having a hard time trying to stop the loop in promise.all if one promise rejects it. Here's how I did it. Is there something wrong with this?
Promise.all(myArray.map((obj) => {
this.someFunction(obj);
}))
Here's the function I call..
someFunction(){
return new Promise(function (resolve, reject) {
....
reject()
})}
I have updated my code, it is tested and it works on my machine with the mock data I feed it with. I am not exactly sure how the rest of your code is structured but it is something likes this: Oh and you cannot break out of a map, but we will use a simple for loop because we can break out of that:
function someFunction(){
return new Promise(function (resolve, reject) {
// I will be rejeccting a boolean
// If you are resolving something, resolve it as true
reject(false)
})}
async function shouldStopLoop(){
// the boolean will come here
// if it is false, the catch block will return
// if it is true, the try block will return
let stopLoop = null;
let result = null;
try {
result = await someFunction();
return result
} catch(error) {
stopLoop = error;
return stopLoop;
}
}
function mayReturnPromiseAll() {
let myArray = ['stuf to loop over...']
let arraytoGoInPrimiseAll = [];
// Array.prototype.map cannot be stopped
// Thats why we will use a for loop and we will push the data we need
// into another array
for (var i = 0; i < myArray.length; i++) {
if (!this.someFunction(obj)) {
break;
} else {
// push things in arraytoGoInPrimiseAll
}
}
if(arraytoGoInPrimiseAll.length > 0){
return Promise.all(arraytoGoInPrimiseAll)
} else {
// do something else
}
};
Try this:
const arrayOfFunctions = myArray.map(obj => this.someFunction(obj))
Promise.all(arrayOfFunctions).then(values => {
console.log(values);
}).catch(error => {
console.log(error)
});

Express - get request - How inject data in my response along the process?

I'm trying to add data to my "data" returned in express. Here my snippet, I'm trying to add currentPage and count variables:
app.get("/blog/page/:pageTargeted", (req,res) => {
var rangeScoped = (req.params.pageTargeted * 8);
Posts.find().sort({ date: -1}).skip(rangeScoped).limit(8).exec(function (err, data) {
data.currentPage= req.params.pageTargeted || 1 ;
data.count = Posts.estimatedDocumentCount();
if (err) return console.error(err);
console.log(data);
res.status(200).send(data)
})
});
I have also tried:
currentPage= req.params.pageTargeted || 1 ;
count = Posts.estimatedDocumentCount();
if (err) return console.error(err);
console.log(data);
res.status(200).send(data currentPage, count)
It doesn't works, currentPage and count aren't add in the res.send toward the browser. I have just the data corresponding to the database get's request. So what it going wrong ? I just can't figure out it. Because to me I have well injected the data into the object so, it should works. If anybody has an hint, would be great.
If I am right data is an array and you can't create a new key in array like that. Try sending an Object instead.
app.get("/blog/page/:pageTargeted", (req,res) => {
var rangeScoped = (req.params.pageTargeted * 8);
Posts.find().sort({ date: -1}).skip(rangeScoped).limit(8).exec(function (err, data) {
if (err) return console.error(err);
console.log(data);
res.status(200).json({data: data, currentPage: req.params.pageTargeted || 1, count: Posts.estimatedDocumentCount()})
})
});

Node JS code not running in order

I have no idea why the code do not run as I expected.
When the UserExist is called, it should either console.log one of the statements that I set in my function code.
But the result is like the following the picture. Apreciate that if somebody can help!!
Console
var sql = require('mssql');
var config = require('./configuration/sqlconfig');
var Username = "Testing";
sql.connect(config);
console.log("Connected to DB");
if (!UserExist(Username)) {
InsertNewRecord(Username);
}
function isEmptyObject(obj) {
return !Object.keys(obj).length;
}
// This should work both there and elsewhere.
function isEmptyObject(obj) {
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
return false;
}
}
return true;
}
function UserExist(Username) {
console.log('Checking whether user exists or not... ');
new sql.Request().query("SELECT * FROM dbo.DB_Users WHERE Username = '" + Username + "';")
.then(function (recordset) {
if (isEmptyObject(recordset)) {
console.log("The User does not exist, ready to insert");
return true;
} else {
console.log("The user is existed already.");
return false;
}
}).catch(function (err) {
//When errors come
});
}
function InsertNewRecord(Username) {
console.log('Attempting to Insert records...');
new sql.Request().query("INSERT INTO dbo.Embright_Users (Username) VALUES ('" + Username + "');");
console.log("Added one new record");
}
The callbacks are not chained correctly. The InsertNewRecord() should be passed as callback to UserExist() function to make sure the execute in sequence. eg:
// Calling UserExist with a callback instead of 'if' statement
UserExist(Username, InsertNewRecord)
function UserExist(Username, callback) {
console.log('Checking whether user exists or not... ');
new sql.Request().query("SELECT * FROM dbo.DB_Users WHERE Username = '" + Username + "';")
.then(function (recordset) {
if (isEmptyObject(recordset)) {
console.log("The User does not exist, ready to insert");
// Calling InsertNewRecord with the username passed
callback(Username);
} else {
console.log("The user is existed already.");
// Do nothing
}
}).catch(function (err) {
//When errors come
});
}