How can I properly set object values inside a promise? - javascript

So I have this object:
let user = {
name: null,
age: null,
sex: null,
created_at: null
}
and I want to set the values based on what the promise returns. The data returned has the same property names.
So the promise is this:
promise.get(/*url*/).then(res => {
const data = res.data;
// set values here
})
I have three ways in my mind right now in setting the property values:
// First
user = data
// Second
user = {
name: data.name,
age: data.age,
sex: data.sex,
created_at: data.created_at
}
// Third
Object.assign(user, data);
Which is the best/proper way? And what are the advantages of one over the other?
I'm currently using the Third option. Any help would be much appreciated.

I like Object.assign()
const user = {
name: 'Ronald Mickdonlad',
age: null,
sex: 'no thanks',
created_at: null
}
const res = {
data: {
name: 'Garbo Hamburgler',
age: 1337,
sex: '0%',
created_at: 133713371337
}
}
//fake DB call
console.log(Object.assign({}, user, res.data))
I was trying to show it with spread operator also, but my REPL apparently doesn't have it, so I gave up. See here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator
This should work also:
return {
...user,
...res.data
}
But, you will need Babel: https://babeljs.io/docs/plugins/transform-object-rest-spread/
I prefer both of those over any other way because it is immutable. You are not reassigning any variables. You are doing read-only once assigned and then creating new objects as you go.
Both Object.assign() and spread operator have right to left precedence, so "newer aka right-most" values will overwrite "older aka left-occurring" values.
Go with this:
const user = {
name: null,
age: null,
sex: null,
created_at: null
}
// if inside an async function
const updatedUserObj = await promise
.get(/*url*/)
.then(res => Object.assign({}, user, res.data))
console.log(updatedUserObj)
Here are a couple more examples to show you Object.assign() further:
const user = {
name: null,
age: null,
sex: null,
created_at: null
}
const someObject = {
coffee: {
good: true,
flavour: 'ultra',
shouldDrink: true,
age: 1337
}
}
// Notice how coffee is the property on the object we just created:
console.log('FIRST EXAMPLE', JSON.stringify(Object.assign({}, someObject), null, 2))
// Notice how someObject is the property on the new object and coffee is its property
console.log('SECOND EXAMPLE', JSON.stringify(Object.assign({}, { someObject }), null, 2))
// Now, watch what happens if we begin overwriting:
console.log('THIRD EXAMPLE', JSON.stringify(Object.assign({}, user, someObject), null, 2))
console.log('FOURTH EXAMPLE', JSON.stringify(Object.assign({}, { user, someObject }), null, 2))
console.log('FIFTH EXAMPLE', JSON.stringify(Object.assign({}, user, { someObject }), null, 2))
console.log('SIXTH EXAMPLE', JSON.stringify(Object.assign({}, { user }, someObject), null, 2))

Option 3 is the better option. In your example with Object.assign(), you are using a factory function to create new instance of your user. The advantage of this is, it doesn't force you to call a constructor of user when you want to create a new user instance. You could also use Object.create()
This is a basic example of Object Orientated Programming.
Read up more here for a better understanding https://www.sitepoint.com/object-oriented-javascript-deep-dive-es6-classes/

Related

Using when with objects in array in Yup

I have the following object:
const values = {
people: [
{
name: "Mark",
age: null
},
{
name: "Shark",
age: 31
}
],
isAgeRequired: false
};
When isAgeRequired flips to true, in my Yup schema I would like to make the age value for each object in the people array require.
I have the following yup schema definition, but right now it seems to validate successfully even if the above requirements are not met:
const validator = object({
people: array(
object({
name: string().required(),
age: number()
.nullable()
.when("isAgeRequired", {
is: true,
then: (schema) => schema.required()
})
})
)
});
The problem is that the parent context is not available in .when, so one way to get around this was to "lift" the .when condition so that it is declared at a level where isAgeRequired is a sibling like so:
// Declare the default person schema separately because I'll want to reuse it.
const person = {
name: string().required(),
age: number().nullable()
}
const validator = object({
people: array(
object(personSchema)
).when('isAgeRequired', (isAgeRequired, schema) => {
if (isAgeRequired) {
return array({
...personSchema,
age: personSchema.age.required() // Override existing age rule and attach .required to it
})
}
return schema;
})
});

When creating a new object with forEach, some prperties show up as $$typeof: Symbol(react.element) React

So I am receiving an array of Objects, each one has a "attributes.seller" property. Then I am using a forEach( ) to go over each one and create a new object with only the properties I need and pushing them to a new array, including the Seller property.
The issue is that on ALL the received objects the "Seller" property exists and its a string.
However, after constructing the new object most of the seller properties show as "seller: {$$typeof: Symbol(react.element), type: 'button', key: null, ref: null, props: {…}, …}"
BUT not all of them, some do show correctly. So IDK whatI am doing wrong if my code was working before and it still works but not for all the items.
This is the object array i am receiving
This is where I itirate over each object:
createdResults.forEach((item) => {
console.log(item.attributes.seller);
const offer = {
itemId: Number(item.attributes.itemId),
token: item.attributes.token,
amount: item.attributes.amount,
price: item.attributes.price,
seller: item.attributes.seller,
};
createdArr.push(offer);
Even when I log out to the console items.attributes.itemId, it shows EVERY SINGLE property just fine.
The issue is after I have pushed each new object into the new array that the "seller" property of it shows like this:
New Object
const getEvents = async () => {
let createdArr = [];
const created = new Moralis.Query("SaleCreateddd");
const createdResults = await created.find();
createdResults.map((item) => {
// Until here, the seller string shows up correctly for each item
console.log(item.attributes.seller);
const offer = {
itemId: Number(item.attributes.itemId),
token: item.attributes.token,
amount: item.attributes.amount,
price: item.attributes.price,
seller: item.attributes.seller,
};
// Its after the forEach loop that the seller property gets distorted
createdArr.push(offer);
itemId is already an integer remove Number()
then you are forgetting .seller
createdResults.forEach((item) => {
console.log(item.attributes.seller);
const offer = {
itemId: item.attributes.seller.Number(itemId),
token: item.attributes.seller.token,
amount: item.attributes.seller.amount,
price: item.attributes.seller.price,
seller: item.attributes.seller.seller,
};
createdArr.push(offer);```

Mongoose update nested object in array of record

I am currently having a problem where I am trying to update an of a nested array in a Mongoose record.My schema is as follows:
const customerSchema = new mongoose.Schema({
kimCustomerId: {
type: Number,
required: true
},
addresses: [
{
created: Date,
updated: Date,
addressInfo: {
type: { type: String },
typeOfAddress: String,
careOf: String,
address: String,
addressRow1: String,
addressRow2: String,
zipcode: String,
city: String,
countryCode: String,
physicalAddressType: String,
validFrom: Date,
validTo: Date
}
}
],
.....
As you can see, the adrress array for each record holds many addresses. I want to be able to pass through an update object and update the properties inside the addressInfo nested object inside a particular array object. Here is my query as it stands:
const updated = await db.models.customers.findOneAndUpdate(
{
_id: customer._id,
'addresses.addressId': addressData.addressId
},
{ $set: { 'addresses.$': addressData } },
{ new: true }
);
and an example of an object I pass through to update a record:
{
addressId: officialAddressExists.addressId,
addressInfo: {
validTo: new Date().toISOString()
}
}
What I want to happen is, when I pass this object to the schema method, I want to select the correct address by the values 'kimCustomerId' and 'addressId' (which I have working fine) then only update the values of the 'addressInfo' nested object that I have passed and keep the ones not passed as they are, in this case the 'validTo' field but it can be any number of them updated. It is overwriting the whole 'addressInfo' nestedObject at the moment so I presume I have to do some kind of set operation on that nested object as well but I am unsure how.
Is anyone able to point me in the right direction here?
Thanks!
There is no straight way to do this in query, you can do it in your client side, something like,
// Sample body request
let addressData = {
addressId: 1,
addressInfo: {
validTo: new Date().toISOString(),
typeOfAddress: "Home",
address: "ABC"
}
};
let set = {};
for (let key in addressData.addressInfo) {
set["addresses.$.addressInfo." + key] = addressData.addressInfo[key];
}
console.log(set);
Pass set variable in to your query,
const updated = await db.models.customers.findOneAndUpdate(
{
_id: customer._id,
'addresses.addressId': addressData.addressId
},
{ $set: set },
{ new: true }
);

return an object with key and value using map

I have a response that should need to return an object with specified key and value using map
I tried
response.data.data = response.data.data.map((user) =>{
return console.log({ user.id : user.name});
});
But it gives me an error due to user.id
how can i set the key coming from response?
this is my data response
data: [
{
id: 2,
name: "Orval McLaughlin",
email: "okoch#example.org",
contacts: "09083692343",
created_at: "2018-09-05 15:08:54",
updated_at: "2018-09-05 15:08:54",
deleted_at: null
}
],
i am using a vue js input tag where in I need a data to bind in a prop
like this
{2: Orval McLaughlin}
It does not make sense to use return console.log(whatever) inside your mapping function because as that will always return undefined .map() will create an array of undefined entries:
let users = [{ id: 1, name: "r2d2" }]
let arr = users.map(user => console.log({ id: user.id, name: user.name}))
console.log(arr);
Instead, change your mapping function to this:
let users = [{
id: 2,
name: "Orval McLaughlin",
email: "okoch#example.org",
contacts: "09083692343",
created_at: "2018-09-05 15:08:54",
updated_at: "2018-09-05 15:08:54",
deleted_at: null
}]
let arr = users.map(user => ({ [user.id]: user.name }))
console.log(arr);
To create a property on an object whose property name you have in a variable propName, use the square brackets notation:
let user = { [propName]: value }
Note that you can also access the property of an object using this notation:
console.log(user[propName]);
To get results like
{2: Orval McLaughlin}
you want a computed property name:
return { [user.id] : user.name};
Note that return console.log(somValue) always returns undefined
console.log() returns undefined, so your current solution gives an array of all undefineds. Instead, you should return the object that you want:
response.data.data = response.data.data.map((user) =>{
return { [user.id] : user.name};
});
Note that you also need to surround the user id key with brackets in order to evaluate the variable.

Property not being added to JS object

So I am trying to add a field to a user object right before I return it and the property is not being added for some reason. Any thoughts?
returnUser = function(userRes) {
console.log(">POST /returnuser< Returning user w/ userId: " + userRes.userId + " deviceToken: " + userRes.deviceToken);
return Location.findOne({
users: {
$elemMatch: {
user: userRes.userId
}
}
}, function(error, response) {
userRes.currentLocation = response;
console.log(userRes);
return res.send(userRes);
});
};
So in the returnUser function I am searching the DB for the user's current location, adding that to the userRes object and then returning it. But when I log the userRes object it doesn't contain that property. Any issue with my code? userRes currently looks like this:
{ _id: 1,
createTime: 1428477183281,
deviceId: '982f24khsd',
deviceToken: 'kjs398fskjjg5fb43ds323',
firstName: 'Cat',
lastName: 'Man',
email: 'cat#mandu.com',
__v: 0,
users: [],
locations: [],
lngLat: [] }
As it turns out, that userRes object is actually a mongoose model instance returned from a mongoose query which is not mutable.
To fix this you can preferably call lean() which will give you a plain JS object instead of a full model instance.
Or if you don't have access to the query you can do something like:
mutableUserRes = JSON.parse(JSON.stringify(userRes));
Which copies the whole object but it is now a simple JS object instead of a mongoose model instance.

Categories

Resources