Use the lastest affected data in an object - javascript

I have this list object that I return:
return ({
name: data.name,
request: {
method: methodLine[index].method.toUpperCase(),
header: data.request.header,
description: data.request.description,
},
response: [
{
originalRequest: request
}
],
})
And I want to use the data stored in the object request while calling it in the response array in the same return statement. Is there a way to do so?

If you want to do it in the return statement, you can use the comma operator to declare two expressions, the first is a variable declaration to declare request and the second is the returned object using request:
const test = () => {
return (request = 'hello', {
request,
response: [{
originalRequest: request
}]
})
}
console.log(test());
However, this is not so readable and I suggest splitting this into a proper variable declaration before the return statement.
const test = () => {
const request = 'hello';
return {
request,
response: [{
originalRequest: request
}]
}
}
console.log(test());

Related

Out of two functions, one can access variable's value, the other can't

The data fetched from API contains two types of elements: cycles which are objects of few attributes, and last_update object, which contains ID and last_update: <date>.
I'm processing them in the following way:
<script>
export default {
data: () => ({
jsonData: [],
lastUpdate: '',
items: [
{
action: 'mdi-calendar',
active: false,
items: [{ title: '' }],
title: 'Last Update',
}
]
}),
methods: {
async parseData() {
const response = await fetch("http://127.0.0.1:5012/api/v3/cycles", {
headers: {
"Content-Type": "application/json",
"mode": "cors"
}
})
let cycles = await response.json();
if (cycles.length < 1) {
console.error("Couldn't fetch cycles from DB...")
}
const last_update = cycles.filter(cycle => cycle.last_update);
this.lastUpdate = last_update[0].last_update;
console.log('Inside parseData:', this.lastUpdate);
cycles = cycles.map(({source, revision, elements}) => ({source, revision, elements}));
this.jsonData = cycles
},
setLastUpdate() {
this.items[0].items.title = this.lastUpdate;
console.log('Inside setLastUpdate:', this.items[0].items.title);
console.log('Inside setLastUpdate:', this.lastUpdate);
}
},
created() {
this.parseData();
this.setLastUpdate();
}
}
</script>
Now, the console shows the following outputs:
Inside setLastUpdate: <empty string>
Inside setLastUpdate: <empty string>
Inside parseData: 2023.01.24 08:44:32
The value gets read and updates the lastUpdate in data section. Why it can't be read by the setLastUpdate() function?
I was thinking that there may be something with async setting, so I made setLastUpdate() function async just for testing, but the asynchronous action in parseData() function only refers to fetching the data from API. After the data is there, all processing happens on the same set of data for both reading cycles and last_update.
How to refactor the code so that the lastUpdate is available for setLastUpdate() function and possibly update the data.items object?
As per looking at the console statement, function setLastUpdate is calling before the parseData function.
So, to make the lastUpdate property available for setLastUpdate, you need to call those functions asynchronously. You can create a single async function that will call both functions one by one and wait for the first to be executed. For example-
created() {
this.init();
},
methods: {
async init() {
await this.parseData();
await this.setLastUpdate();
},
},
One more thing-
instead of-
this.items[0].items.title = this.lastUpdate;
It should be-
this.items[0].items[0].title = this.lastUpdate;
Because inner items is having an array of objects structure.

ReactJS axios.post inside a map through array function that returns an object

So I try to map through an array and for each item in the array is a parameter value for a post request. So Im looking for an finalArray with the post request response return value, and need to use the finalArray somewhere else.
const finalArray = paramArray.map(paramKey => {
axios.post(URL, {
filters: [
{
field: "key",
values: [paramKey.key]
}
]
}).then(res => {
//res.data.itemName
});
return {
key: paramKey.key,
text: //res.data.itemName,
value: paramKey.value
}
});
so Im not sure how to pass the res.data.itemName outside of the function in .then. I tried declaring a variable before axios such as let name = "";, and inside .then I have name = res.data.itemName, then I pass the name to text as text: name, but this will give me all empty string. I also tried putting the return inside .then, this way the finalArray gives me undefined values.
Is there any way to pass the res.data.itemName as the value of text?
You can use Promise.all
async function() {
const promises = paramArray.map(paramKey => axios.post(URL, {
filters: [
{
field: "key",
values: [paramKey.key]
}
]
})
);
const values = await Promise.all(promises)
const finalArray = paramArray.map((paramKey, index) => {
return {
key: paramKey.key,
text: values[index].data.itemName,
value: paramKey.value
}
})
}

Axios multiple values (comma separated) in a parameter

Expected query string:
http://fqdn/page?categoryID=1&categoryID=2
Axios get request:
fetchNumbers () {
return axios.get(globalConfig.CATS_URL, {
params: {
...(this.category ? { categoryId: this.category } : {})
}
})
.then((resp) => {
// console.log(resp)
})
.catch((err) => {
console.log(err)
})
}
As you can see, it works perfectly with just 1 value for 1 parameter, but if i wanted to make multiple values - it doesn't work, i've tried to use an array:
...(this.category ? { categoryId: [1, 2] } : {})
But it returns this way:
http://fqdn/page?categoryID[]=1&categoryID[]=2
So it just not working. Had a look at this issue: Passing an object with a parameter with multiple values as a query string in a GET using axios
But can't figure out, how he solved this problem.
You can use Axios's paramsSerializer to customize the serialization of parameters in the request.
Note that URLSearchParams serializes array data the way you're expecting:
const searchParams = new URLSearchParams();
searchParams.append('foo', 1);
searchParams.append('foo', 2);
console.log(searchParams.toString()); // foo=1&foo=2
So you could use that class in paramsSerializer as follows:
// my-axios.js
export default axios.create({
paramsSerializer(params) {
const searchParams = new URLSearchParams();
for (const key of Object.keys(params)) {
const param = params[key];
if (Array.isArray(param)) {
for (const p of param) {
searchParams.append(key, p);
}
} else {
searchParams.append(key, param);
}
}
return searchParams.toString();
}
});
// Foo.vue
import axios from './my-axios.js';
export default {
methods: {
async send() {
const { data } = await axios({
url: '//httpbin.org/get',
params: {
categoryId: [1, 2, 3]
}
});
// ...
}
}
}
demo
This is not an axios related issue. It depends on whether your backend service is able to understand query params in this fashion(seems to be framework dependent). From your question, I think it is not working when queryParams like following are sent
?categoryID[]=1&categoryID[]=2
and it expects
?categoryID = 1,2
What you can do is transform array to such string before passing it to params in axios. Update the following piece in your code and it should solve your problem.
...(this.category ? { categoryId: this.category.join(',') } : {})
Take a look at following thread
How to pass an array within a query string?

Working with a message having repeated field

My Proto file looks like this -
message Todos {
repeated Todo todos = 1;
}
message Todo {
int32 id = 1;
string name = 2;
bool done = 3;
}
It comes works fine when I send {todos: [...]} from the server, but gets an empty object {} when directly sending an array.
Server
getAll(_, callback) {
console.log(todos);
return callback(null, { todos });
}
Client
client.getAll({}, function (err, res) {
if (err) {
return console.log(err);
}
console.log('todos: ');
return console.log(res);
});
Versions -
#grpc/proto-loader - ^0.1.0
grpc - ^1.13.0
In my case I was trying to return an array and it seems you always have to return an object....
hero.proto
syntax = "proto3";
package hero;
service HeroService {
rpc GetHeroById(HeroById) returns (Hero) {}
rpc ListHeroesById(HeroById) returns (HeroList) {}
}
message HeroById {
int32 id = 1;
}
message Hero {
int32 id = 1;
string name = 2;
}
message HeroList {
repeated Hero heroes = 1;
}
hero.controller.ts
#GrpcMethod('HeroService')
listHeroesById(data: HeroById, metadata: any): object {
const items = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Doe' },
{ id: 3, name: 'Billy' },
];
// make sure you return an object, even if you want an array!
return { heroes: items.filter(({ id }) => id === data.id) };
}
Check out my example TypeScript project here:
https://github.com/kmturley/angular-nest-grpc
If I understand correctly, you are having problems if you send just the array todos, instead of an object containing that array. Sending just the array is simply an invalid use of the API. Protobuf services always send protobuf messages, so you have to pass an actual message object, and not a single field of that object.
If you use grpc.load then you can send back an array:
callback(null, todos);
If you use protoLoader.loadSync and grpc.loadPackageDefinition, then you need to send back:
callback(null, { todos: todos });

Access Observable values and assign to a collection

I am receiving an Observable back from an Angular service and I can see the data coming back from the service when it resolves using .subscribe
returnedObservable$.subscribe(res => {
console.log(res);
return res;
]);
I have tried assigning this to an Object inside of the .subscribe but the assignment isn't happening.
let newObj = {};
returnedObservable$.subscribe(res => newObj = res);
How can I make this assignment to get the values out of the Observable?
The first time it tries to access the response the result is null but eventually resolves.
The console.log(res) looks like this:
{
itemList: [
{ id: 1, name: Steve },
{ id: 2, name: Bob },
{ id: 3, name: Tim }
]
}
You can use it like this:
let newObj = {};
returnedObservable$.subscribe(res => {newObj = res}).add(()=>
{
//Use your object here
console.log(newObj);
});

Categories