Populate array objects from result inside a Function [duplicate] - javascript

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 5 years ago.
I need to call the result(array from a function) Called outside the function
My Code look likes this
import axios from 'axios'
var cheats
(() => {
axios.get('api/cheats/getcheaternames')
.then((response) => {
cheats = response.data
console.log(cheats, 'yeah')//results[Good, Bad]
return cheats
})
.catch((error) => {
console.log(error, 'err')
})
})()
const it = [
{
name: ...
}
]
This is how I hardcode the result,
const it = [
{
name: 'Good'
},
{
name: 'Bad'
},
{
name: 'Handsome'
}
]
Any idea to dynamically populate the it variable?
Update
I have no enough reputation to answer my own question, here it is how I refactor my code to make it work
import axios from 'axios'
var cheats
var it = []
let myFirstPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(axios.get('api/cheats/getcheaternames')
.then((response) => {
cheats = response.data
return cheats
})
.catch((error) => {
console.log(error, 'err')
}))
}, 250)
})
myFirstPromise.then((successMessage) => {
// for (var i = 0; i < successMessage.length; i++) {
// it.push({name: i})
// }
for (const value of successMessage) {
it.push({name: value})
}
})
export default {
items: [
{
name: 'Dashboard',
url: '/dashboard',
icon: 'icon-speedometer',
badge: {
variant: 'primary',
text: 'Cheaters'
}
},
{
title: true,
name: 'Elements',
class: '',
wrapper: {
element: '',
attributes: {}
}
},
{
name: 'Cheats',
url: '/components',
icon: 'icon-puzzle',
children: it
},
{
name: 'Angular Version',
url: 'https://angular.herokuapp.com/',
icon: 'icon-cloud-download',
class: 'mt-auto',
variant: 'success'
}
]
}
Any idea to make this code better is appreciated. Am I missing something or am I doing right with this code?

Not entirely clear what you're asking, but if you're asking how to change the items variable, change it to have let instead of const and change your code to:
.then((response) => {
cheats = response.data;
console.log(cheats, 'yeah')//results[Good, Bad]
items = response.data.map(item => ({ name: item }));
return cheats
})

Related

Get source in constructor

I'm trying to make a search with autocomplete, tell me how I can get in the constructor an array of label and results with axios get
new Autocomplete(input, {
source: (response) => {
axios.get('{{ route('api.autocomplete) }}', {
params: {
term: input.value
}
})
.then(response => {
return {
label: response.data.name,
results: response.data.children,
}
})
},
select: ({element}) => {
alert(element);
}
});
class Autocomplete {
constructor(element, {
source = () => {},
select = () => {},
}) {
console.log(source);
}
}
Instead of an array, it gives out a piece of axios request code

Realm Error: Failed to read ObjectSchema: JS value must be of type 'object', got

I am trying to add a to in my local storage using realm when I click the add button, here is my code as I've I was following the documentation and tried to tweak it my own way
const addToDo = () => {
Realm.open({
schema: [
'Todo',
{
properties: {
name: 'string',
},
},
],
})
.then((realm) => {
realm.write(() => {
realm.create('Todo', {name: todo});
// realm.close();
});
setData({realm});
})
.catch((err) => console.log(err));
};

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

Why my Array is a empty after .then()? JavaScript [duplicate]

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 4 years ago.
I wrote a controller and I do not understand why in the method then my array is correct and I need to send it, and for .then () my array is empty. I can not send a res in the middle of the loop.
exports.getRecipientdata = (req, res) => {
const userId = req.params.recipientId;
const sendersArray = [];
Transaction.findAll({
where: {
id_recipient: userId,
},
}).then(transactions => {
for (let i = 0; i < transactions.length; i++) {
User.findOne({
where: {
id: transactions[i].id_sender,
},
attributes: ['id', 'name', 'surname'],
include: [
{
model: Transaction,
where: { id_sender: db.Sequelize.col('user.id') },
attributes: [
'amount_money',
'date_time',
'transfer_title',
'id_recipient',
'id_sender',
],
},
],
})
.then(sender => {
sendersArray.push(sender);
console.log(JSON.stringify(sendersArray)); // ok
})
.catch(err => {
console.log(err);
});
}
console.log('sendersArray', sendersArray); // empty?
res.send(sendersArray);
});
};
The for loop is sending out requests which asynchronously populate sendersArray. If you console.log(sendersArray) synchronously after the for loop has run, it won't have been populated yet. Instead of a for loop, use .map and Promise.all to wait for all requests to complete:
exports.getRecipientdata = (req, res) => {
const userId = req.params.recipientId;
const sendersArray = [];
Transaction.findAll({
where: {
id_recipient: userId,
},
}).then(transactions => {
return Promise.all(transactions.map(({ id_sender }) => (
User.findOne({
where: {
id: id_sender,
},
attributes: ['id', 'name', 'surname'],
include: [
{
model: Transaction,
where: { id_sender: db.Sequelize.col('user.id') },
attributes: [
'amount_money',
'date_time',
'transfer_title',
'id_recipient',
'id_sender',
],
},
],
})
.then(sender => {
sendersArray.push(sender);
})
.catch(err => {
console.log(err);
})
)));
})
.then(() => {
res.send(sendersArray);
});
};
Another possibility, rather than pushing to an outer variable, would be to use the array created by Promise.all, and filter by boolean to remove the falsey values (since the catch's lack of a return value will have resulted in undefineds being present in the result of the Promise.all array):
exports.getRecipientdata = (req, res) => {
const userId = req.params.recipientId;
Transaction.findAll({
where: {
id_recipient: userId,
},
}).then(transactions => {
return Promise.all(transactions.map(({ id_sender }) => (
User.findOne({
where: {
id: id_sender,
},
attributes: ['id', 'name', 'surname'],
include: [
{
model: Transaction,
where: { id_sender: db.Sequelize.col('user.id') },
attributes: [
'amount_money',
'date_time',
'transfer_title',
'id_recipient',
'id_sender',
],
},
],
})
.catch(err => {
console.log(err);
})
)));
})
.then((sendersArray) => {
res.send(sendersArray.filter(Boolean));
});
};

eslint arrow-body-style issue

I configured my eslint so it uses the arrow-body-style as needed:
arrow-body-style: ["error", "as-needed"]
But I'm getting an error below for some reason.
router.get('/', (req, res, next) => {
Product.find({})
.select('name price _id')
.then(items => {
const response = {
count: items.length,
products: items.map(item => { // eslint points the error here
return {
name: item.name,
price: item.price,
_id: item._id,
request: {
type: 'GET',
url: `http://localhost:3000/products/${item._id}`
}
};
})
};
res.status(200).json(response);
})
.catch(error => {
console.log(error);
res.status(500).json({ message: 'Server error' });
});
});
How exactly am I supposed to re-write my code?
Using arrow-body-style: ["error", "as-needed"] configuration is redundant as it is the default behaviour. You don't need setting it again as it is already set as the default form.
as-needed
Examples of incorrect code for this rule with the default "as-needed" option:
/*eslint arrow-body-style: ["error", "as-needed"]*/
/*eslint-env es6*/
let foo = () => {
return 0;
};
let foo = () => {
return {
bar: {
foo: 1,
bar: 2,
}
};
};
Examples of correct code for this rule with the default "as-needed" option:
/*eslint arrow-body-style: ["error", "as-needed"]*/
/*eslint-env es6*/
let foo = () => 0;
let foo = (retv, name) => {
retv[name] = true;
return retv;
};
let foo = () => ({
bar: {
foo: 1,
bar: 2,
}
});
let foo = () => { bar(); };
let foo = () => {};
let foo = () => { /* do nothing */ };
let foo = () => {
// do nothing.
};
let foo = () => ({ bar: 0 });
ESLint Docs on arrow-body
In your code sample it should be this way:
router.get('/', (req, res, next) => {
Product.find({})
.select('name price _id')
.then(items => {
const response = {
count: items.length,
products: items.map(item => ({ // no more errors
name: item.name,
price: item.price,
_id: item._id,
request: {
type: 'GET',
url: `http://localhost:3000/products/${item._id}`
});
})
};
res.status(200).json(response);
})
.catch(error => {
console.log(error);
res.status(500).json({ message: 'Server error' });
});
});
Since you're simply returning a plain object, there's no need for the extra pair of braces and return. Wrapping the object in parentheses ({ ... }), works as that is implicitly returned.
Try to omit return keyword and wrap the result into parenthesis:
products: items.map(item => ({
name: item.name,
price: item.price,
_id: item._id,
request: {
type: 'GET',
url: `http://localhost:3000/products/${item._id}`
}
}))

Categories