JavaScript ignoring adding object to array - javascript

function setUsersDefinitions(data, userID){
let users = new Array();
return new Promise((resolve)=>{
data.forEach(el => {
if (el.id_adder === userID) {
getUserName(el.id_added).then(u => {
users.push({
username: u,
locked: el.locked !== null,
canUnlock: el.locked === userID,
id: el.id_added
})
}).catch(e=>{
console.log(e);
})
} else {
getUserName(el.id_adder).then(u=>{
users.push({
username: u,
locked: el.locked !== null,
canUnlock: el.locked === userID,
id: el.id_adder
})
}).catch(e=>{
console.log(e);
})
}
})
resolve(users);
})
}
The problem is that when i try doing a console.log of the item generated it works but when it call Array.push method, it ignore that command.
What am I doing wrong?
Thanks in advance.

All of this should be done with async/await, and not by wrapping the whole lot in a Promise - it will hugely simplify your code:
async function setUsersDefinitions(data, userID){
let users = new Array();
for(var i=0;i<data.length;i++){
var el = data[i];
var id = (el.id_adder === userID) ? el.id_added : el.id_adder;
var u = await getUserName(id);
users.push({
username: u,
locked: el.locked !== null,
canUnlock: el.locked === userID,
id: id
});
}
return users;
}
(Note: Error handling omitted for brevity)
You should then await this function wherever you call it (must itself be within an async function):
async function doWork(){
var users = await setUsersDefinitions(some_data, some_userID);
console.log(users);
}

Related

Nodejs Execute after a recursive function is done

I have a controller that basically performs a recursive call to retrieve how categories and their deleted items, but a "category_item" has a property called "next_steps" which is an array of categories, so I need to retrieve those categories and their items as well.
So I made a recursive function, it works, but I need to run something else when it actually ends, how can I do that? here's my code:
const recoveryCategory = async (req, res) => {
try {
const categoryId = req.params.categoryId
const category = await nmCategorySvcV2.getByIdDeleted(categoryId)
if (category === null){
throw new Error("This category is not deleted.")
}
__recoveryRecursive(categoryId)
// run something after
res.json({ success: true, message: "Success." })
} catch (err){
res.json({ success: false, message: err.message })
}
}
const __recoveryRecursive = async (categoryId) => {
const category = await nmCategorySvcV2.getByIdDeleted(categoryId)
if (category === null){
return
}
await nmCategorySvcV2.update(categoryId, { deleted: false })
const categoryItens = await categoryItemSvcV2.getAllItensByCategory(categoryId)
for (let i = 0; i < categoryItens.length; i++) {
const categoryItem = categoryItens[i]
if (categoryItem.deleted == true) {
const item = await itemSvcV2.getByIdNoPopulate(categoryItem.item, categoryItem.page)
if (item.deleted == true) {
itemSvcV2.update(item._id, { deleted: false })
categoryItemSvcV2.updateItensProp(item._id, { deleted: false })
}
const itemPrice = await itemPriceSvcV2.getById(categoryItem.price)
if (itemPrice.deleted == true) {
itemPriceSvcV2.updateObject({ _id: itemPrice._id }, { deleted: false })
}
categoryItemSvcV2.update(categoryItem._id, { deleted: false })
if (categoryItem.next_steps.length > 0){
for (let j = 0; j < categoryItem.next_steps.length; j++){
const categryNextStep = categoryItem.next_steps[j].category
__recoveryRecursive(categryNextStep)
}
}
}
}
}
Just add await before the recursive call because it returns a promise wich must be handled .

Firebase function to get ranking

I am new to firebase and would like to implement the ranking for the players stored in the rank table from firebase real-time db, see screenshot below:
I have also setup the rules for the index:
{
"rules": {
".read": "auth != null",
".write": "auth != null",
"TH": {
"rank": {
".indexOn" : ["balance", "w_rate","match"]
}
}
}
}
in my firebase function, I have a function as a post request to get the rank:
exports.getRank = functions.https.onRequest(async (req,res) => {
const user_id = req.query.id;
console.log(`user_id ${user_id} `);
const query = database().ref('TH/rank')
.orderByChild('balance')
.limitToLast(30)
query.once('value',function(snapshot) {
console.log('in side the usersRef');
console.log(`snapshot:${JSON.stringify(snapshot.val())}`);
let current_user_rank = 0;
if (user_id !== null) {
console.log(`user id ${user_id} isn't null`);
database().ref('TH/rank/').orderByChild('balance').once('value',function(all_snapshot){
let index = 0;
console.log(`user id ${user_id} all snapshot.`);
if (all_snapshot.child(`${user_id}`).exists()) {
console.log(`user id ${user_id} exists`);
const current_user_data = all_snapshot.child(`${user_id}`).val();
all_snapshot.forEach( child => {
index += 1;
console.log(child.key, child.val());
if(child.key === user_id) {
current_user_rank = all_snapshot.numChildren() - index;
}
});
res.json({
user: { id: user_id,
rank: current_user_rank,
data: current_user_data
},
rank: snapshot.val()
});
} else {
res.json({
user: { id: user_id,
rank: current_user_rank,
data: null
},
rank: snapshot.val()
});
}
}).catch();
} else {
res.json({
user: { id: user_id,
rank: current_user_rank,
data: null
},
rank: snapshot.val()
});
}
}).catch();
});
However, the result isn't correct, it seems the orderByChild doesn't work at all. Can someone help on this?
Thanks.
There are several problems with your Cloud Function:
You use async when declaring the callback but you never use await in the Cloud Function, in order to get the result of the asynchronous once() method.
Instead of using the callback "flavor" of the once() method (i.e. ref.once('value',function(snapshot) {..}), use the promise "flavor" (i.e., with await: await ref.once('value');).
The result is that you don't correctly manage the Cloud Function life cycle. For more details on how to do that correctly, I would suggest you watch the 3 videos about "JavaScript Promises" from the Firebase video series as well as read the following doc.
So the following should do the trick. (Note that I've just adapted it to correctly manage the life cycle, I've not tested the business logic).
exports.getRank = functions.https.onRequest(async (req, res) => {
try {
const user_id = req.query.id;
console.log(`user_id ${user_id} `);
let current_user_rank = 0;
if (user_id !== null) {
console.log(`user id ${user_id} isn't null`);
const baseQuery = database().ref('TH/rank/').orderByChild('balance');
const query = baseQuery.limitToLast(30);
const snapshot = await query.once('value');
console.log(`snapshot:${JSON.stringify(snapshot.val())}`);
const all_snapshot = await baseQuery.once('value');
let index = 0;
console.log(`user id ${user_id} all snapshot.`);
if (all_snapshot.child(`${user_id}`).exists()) {
console.log(`user id ${user_id} exists`);
const current_user_data = all_snapshot.child(`${user_id}`).val();
all_snapshot.forEach(child => {
index += 1;
console.log(child.key, child.val());
if (child.key === user_id) {
current_user_rank = all_snapshot.numChildren() - index;
}
});
res.json({
user: {
id: user_id,
rank: current_user_rank,
data: current_user_data
},
rank: snapshot.val()
});
} else {
res.json({
user: {
id: user_id,
rank: current_user_rank,
data: null
},
rank: snapshot.val()
});
}
} else {
res.json({
user: {
id: user_id,
rank: current_user_rank,
data: null
},
rank: snapshot.val()
});
}
} catch (error) {
console.log(error);
res.status(500).send(error);
}
});
Update following your comment:
You need to use forEach() in order to get the children correctly ordered, and not snapshot.val(). snapshot.val() displays the children according to their key, exactly like they are ordered in the DB. The following adaptation of the code in your comment works correctly:
exports.getSortedRank = functions.https.onRequest(async (req, res) => {
try {
const obj = {};
const baseQuery = admin.database().ref('TH/rank/').orderByChild('balance');
const query = baseQuery.limitToLast(10);
const snapshot = await query.once('value');
snapshot.forEach(childSnapshot => {
console.log(childSnapshot.val());
obj[childSnapshot.key] = childSnapshot.val()
});
res.json({ rank: obj });
} catch (error) { console.log(error); res.status(500).send(error); }
});

function is returning undefined javascript

I wrote a function in javascript expression to check if the result is true or false but i am always getting undefined error
var array = [{
email: 'usman#gmail.com',
password: '123'
},
{
email: 'ali#gmail.com',
password: '123'
}
];
let main = function(email, password) {
return array.forEach((row) => {
if (row.email === email && row.password === password) {
return true
} else {
return false
}
});
};
var checkLogin = main('usman#gmail.com', '123');
console.log(checkLogin)
checkLogin always return undefined
It's because forEach does not return anything. You can use simple for-loop, like this:
var array = [
{email: 'usman#gmail.com', password: '123'},
{email: 'ali#gmail.com', password: '123'}
];
let main = function(email, password) {
for (var i = 0; i < array.length; i++) {
var row = array[i];
if (row.email === email && row.password === password) {
return true
}
}
return false;
};
var checkLogin = main('usman#gmail.com', '123');
console.log(checkLogin)
Also, take a look at some(), includes(), find() and findIndex()
The forEach array function doesn't return anything. If you touch looped array inside it then you are able to modify existing array without copying it.
there's a problem with foreach. it doesn't return anything
var array = [
{email: 'mike#gmail.com', password: '123'},
];
let main = function(email, password) {
for (var i = 0; i < array.length; i++) {
if (array[i].email === email && array[i].password === password) {
return true
}
};
return false
};
var checkLogin = main('mike#gmail.com', '123');
console.log(checkLogin) // returns true
there is something wrong with this logic:
return array.forEach((row) => {
if (row.email === email && row.password === password) {
return true
} else {
return false
}
});
without this logic it returns anything you want
You could take Array#some and return the result of the check.
var array = [{ email: 'ali#gmail.com', password: '123' }, { email: 'usman#gmail.com', password: '123' }];
let main = (email, password) =>
array.some(row => row.email === email && row.password === password);
var checkLogin = main('usman#gmail.com', '123');
console.log(checkLogin)

How to use DataLoader with Mongoose

I'm trying to build the following use case of DataLoader together with Mongoose:
export const PurchaseOrderType = new GraphQLObjectType({
name: "PurchaseOrder",
description: "PurchaseOrder",
interfaces: () => [NodeInterface],
isTypeOf: value => value instanceof PurchaseOrderModel,
fields: () => ({
id: {
type: new GraphQLNonNull(GraphQLID),
resolve: obj => dbIdToNodeId(obj._id, "PurchaseOrder")
},
name: {
type: new GraphQLNonNull(GraphQLString)
},
customer: {
type: CustomerType,
resolve: (source, args, context) => {
return context.customerLoader.load(source.customer_id);
}
}
})
});
export default () => {
return graphqlHTTP((req, res, graphQLParams) => {
return {
schema: schema,
graphiql: true,
pretty: true,
context: {
customerLoader: customerGetByIdsLoader()
},
formatError: error => ({
message: error.message,
locations: error.locations,
stack: error.stack,
path: error.path
})
};
});
};
export const customerGetByIdsLoader = () =>
new DataLoader(ids => {
return customerGetByIds(ids);
});
export const customerGetByIds = async ids => {
let result = await Customer.find({ _id: { $in: ids }, deletedAt: null }).exec();
let rows = ids.map(id => {
let found = result.find(item => {
return item.id.equals(id);
});
return found ? found : null; << === found always undefined
});
return rows;
};
I'm facing the following problems when loading several PurchaseOrders:
A single customer_id is being called more than once in the ids parameter of the DataLoader. So an example id 5cee853eae92f6021f297f45 is being called on several requests to my loader, in successive calls. That suggests that the cache is not working properly.
My found variable when processing the read result is always being set to false, even comparing the right ids.
You can use findOne
export const customerGetByIds = async ids => {
let result = await Customer.find({ _id: { $in: ids }, deletedAt: null }).exec();
const rows = []
let promiseAll = ids.map(async (id) => {
let found = result.filter(item => item.id.toString() === id.toSring());
if(found) {
rows.push(found[0])
return found[0]
}
return null;
});
await Promise.all(promiseAll);
return rows;
};

Time delay in child_added listener

I want to add a new team member if team member not exists in the Firebase database. However I see a time delay while reading the existing entries. The below code returns null for the variable teammembertKey. Therefore I see a new key in database every time I re-login into the system. Can someone help me to solve this issue?
checkIfUserExists = function (teammemberData) {
return firebase.database().ref().child('/leaders/' + firebase.auth().currentUser.uid)
.once("value", function (snapshot) {
console.log(snapshot.exists());
return Promise.resolve({
teammemberData,
userExists: snapshot.exists(),
});
});
};
$scope.submit = function () {
var teammembertKey = null;
// A teammember entry.
// A teammember entry.
var teammemberData = {
uid: firebase.auth().currentUser.uid,
email: firebase.auth().currentUser.email,
displayName: firebase.auth().currentUser.displayName,
photoURL: firebase.auth().currentUser.photoURL
};
const p = checkIfUserExists(teammemberData);
p.then((snapshot, userExists) => {
if (userExists) {
teammembertKey = snapshot.key;
// update user
} else {
// go create a user
console.log('i');
}
})
.catch(err => {
console.warn('Error signing in.', err);
});
if (teammembertKey == null) {
// Get a key for a new team member.
teammembertKey = firebase.auth().currentUser.uid; //firebase.database().ref().push().key;
// Write the new member's data simultaneously.
var updates = {};
updates['/leaders/' + teammembertKey] = teammemberData;
const promise = firebase.database().ref().update(updates);
promise
.then(e => { })
.catch(e => {
console.log(e);
})
}
};
Here is what you need.
$scope.submit = function () {
var teammembertKey = firebase.auth().currentUser.uid;
var teammemberData = {
uid: firebase.auth().currentUser.uid,
email: firebase.auth().currentUser.email,
displayName: firebase.auth().currentUser.displayName,
photoURL: firebase.auth().currentUser.photoURL
};
firebase.database().ref().child('/leaders/' + teammembertKey).once("value")
.then(funciton(snap) {
if(!snap.val()) {
var updates = {};
updates['/leaders/' + teammembertKey] = teammemberData;
const promise = firebase.database().ref().update(updates);
promise
.then(e => { })
.catch(e => {
console.log(e);
})
}
})
.catch(err => {
console.warn('Error signing in.', err);
});
};

Categories