Loaded fields are not initialized in the additional function - javascript

I use two functions to load some components for my page and save it in two fields representatives and allUsers. Then I try to use additional func subtractSets() to a little bit modify loaded data. My problem is that fields this.representatives and this.allUsers in this adittional function are still not initialized. What I can do to get loaded data in subtractSets()?
setup() {
const representatives = ref([])
const allUsers = ref([])
data() {
return {
representatives,
users
}
}
},
methods(): {
loadUsersRepresentatives() {
axios.get('getRepresentatives').then(res => {
this.representatives = res.data
}).catch(() => {
...
})
});
},
loadAllUsers() {
axios.get('/getAllUsers').then(res => {
this.allUsers = res.data
}).catch(() => {
...
})
});
},
subtractSets(obj1, obj2) {
...
},
showRepresentativesDialog(facultyID) {
this.loadUsersRepresentatives(facultyID)
this.loadAllUsers()
this.subtractSets(this.representatives, this.allUsers)
this.representativesDialog = true
}
},
´´´

You are missing async / await
methods(): {
async loadUsersRepresentatives() {
return axios.get('getRepresentatives').then(res => {
this.representatives = res.data
}).catch(() => {
...
})
});
},
async loadAllUsers() {
return axios.get('/getAllUsers').then(res => {
this.allUsers = res.data
}).catch(() => {
...
})
});
},
subtractSets(obj1, obj2) {
...
},
async showRepresentativesDialog(facultyID) {
await this.loadUsersRepresentatives(facultyID)
await this.loadAllUsers()
this.subtractSets(this.representatives, this.allUsers)
this.representativesDialog = true
}
},

Related

Async await in for loop

I have this function and I'm trying to push objects into the "groupData" array and then return the response object but when the function successfully runs, I get "response" as a null object. What is wrong with my code can anyone help? How can I make the function to wait for the map function to finish and then return.
const groupList = async (io, socket, userid) => {
var response = {};
try {
var groupData = [];
ddb.get({
TableName: "Tablename",
Key: { Username: userid },
})
.promise()
.then(async (user) => {
if (Object.keys(user).length === 0) {
} else {
const groups = user.Item.Chatgroups;
groups.map((g) => {
ddb.get({
TableName: "Tablename",
Key: { ChatID: g },
})
.promise()
.then(async (data) => {
groupData.push({
ChatID: g,
Chatname: data.Item.Chatname,
Group: data.Item.Group
});
})
.catch((err) => {
console.log("Chat group not found");
});
})
response["groups"] = groupData;
}
})
.catch((err) => {
response["code"] = 400;
response["message"] = "Something Went Wrong";
});
} catch (error) {
console.log(error);
} finally {
return response;
}
};
Use Promise.all and if you use async then make use of await.
Here is how your code could look. I removed the error handling -- first test this and when it works, start adding back some error handling (with try/catch):
const groupList = async (io, socket, Username) => {
const user = await ddb.get({
TableName: "Tablename",
Key: { Username },
}).promise();
if (!Object.keys(user).length) return {};
return {
groups: await Promise.all(user.Item.Chatgroups.map(async ChatID => {
const { Item: { Chatname, Group } } = await ddb.get({
TableName: "Tablename",
Key: { ChatID },
}).promise();
return { ChatID, Chatname, Group };
}))
};
};
I searched too long for this 😭
for await (item of items) {}

Array is empty after api call using vuejs3

I'm using vue-js and i encountered this problem where i call a get all api and then store it in an array. The logic works perfectly fine in the first component, however when i copied literally the exact same code and pasted it in a second component the call for some reason returns an empty array instead of the array of users. Here is the component
import UsersInServiceCenterService from "../services/UsersInServiceCenterService";
import UserService from "../services/UserService";
export default {
name: "service center",
data() {
return {
currentServiceCenter: null,
message: '',
listOfSpecificServiceCenter1: [],
listOfSpecifiedUsers1: [],
id:"",
};
},
methods: {
getServiceCenter(id) {
ServiceCenterService.get(id)
.then((response) => {
this.currentServiceCenter = response.data;
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
},
updateServiceCenter() {
ServiceCenterService.update(this.currentServiceCenter.id, this.currentServiceCenter)
.then((response) => {
console.log(response.data);
this.message = "The service center was updated successfully!";
})
.catch((e) => {
console.log(e);
});
},
deleteServiceCenter() {
ServiceCenterService.delete(this.currentServiceCenter.id)
.then((response) => {
console.log(response.data);
this.$router.push({ name: "service centers" });
})
.catch((e) => {
console.log(e);
});
},
retrieveAllUsersByServiceCenterId(currentServiceCenter){
UsersInServiceCenterService.getAllUsersByServiceCenterId(currentServiceCenter.id)
.then((response) => {
this.listOfSpecificServiceCenter1 = response.data;
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
},
retrieve(){
this.retrieveAllUsersByServiceCenterId(this.currentServiceCenter);
if(this.listOfSpecificServiceCenter1.length!=0){
for(var i =0 ; i<this.listOfSpecificServiceCenter1.length;i++){
UserService.get(this.listOfSpecificServiceCenter1[i].userId)
.then((response) => {
this.listOfSpecifiedUsers1.push(response.data);
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
}
}
this.isEmpty = !this.isEmpty;
},
},
mounted() {
this.message = "";
this.getServiceCenter(this.$route.params.id);
},
};
</script>
getServiceCenter(id) works fine and it returns the service center. However both of the retrieve() and the retrieveAllUsersByServiceCenterId(currentServiceCenter) do not work at all and they return the empty array. Here is the first component which works totally fine with literally the exact same functions.
import UserService from "../services/UserService";
import UsersInServiceCenterService from "../services/UsersInServiceCenterService";
export default {
name: "servicecenters-list",
data() {
return {
serviceCenters: [],
users:[],
currentServiceCenter: null,
currentUser: null,
currentIndex: -1,
currentUserIndex: -1,
id: "",
searchValue: "",
isEmpty: false,
rows: [],
listOfSpecificServiceCenter:[],
listOfSpecifiedUsers:[],
};
},
methods: {
retrieveServiceCenters() {
ServiceCenterService.getAllServiceCenters()
.then((response) => {
this.serviceCenters = response.data;
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
},
retrieveUsers() {
UserService.getAllUsers()
.then((response) => {
this.users = response.data;
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
},
refreshList() {
this.retrieveServiceCenters();
//this.retrieveUsers();
this.currentServiceCenter = null;
this.currentIndex = -1;
//this.currentUser = null;
//this.currentUserIndex = -1;
},
setActiveServiceCenter(servicecenter, index) {
this.currentServiceCenter = servicecenter;
this.currentIndex = index;
},
setActiveUser(user,userIndex){
this.currentUser= user;
this.currentUserIndex = userIndex;
},
// showList(currentServiceCenter){
// for(var i =0;i<currentServiceCenter.users.length;i++){
// }
// },
retrieve(){
this.retrieveAllUsersByServiceCenterId(this.currentServiceCenter);
if(this.listOfSpecificServiceCenter.length!=0){
for(var i =0 ; i<this.listOfSpecificServiceCenter.length;i++){
UserService.get(this.listOfSpecificServiceCenter[i].userId)
.then((response) => {
this.listOfSpecifiedUsers.push(response.data);
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
}
}
this.isEmpty = !this.isEmpty;
},
retrieveAllUsersByServiceCenterId(currentServiceCenter){
UsersInServiceCenterService.getAllUsersByServiceCenterId(currentServiceCenter.id)
.then((response) => {
this.listOfSpecificServiceCenter = response.data;
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
},
addUserToServiceCenter(currentServiceCenter, currentUser) {
var data = {
serviceCenterId: parseInt(this.currentServiceCenter.id),
userId: parseInt(this.currentUser.id),
};
UsersInServiceCenterService.add(data)
.then((response) => {
//this.currentServiceCenter.id = response.data.id; //take care here
console.log(response.data);
this.submitted = true;
})
.catch((e) => {
console.log(e);
});
this.show=false
if(currentServiceCenter.users == Array.isArray(currentServiceCenter.users))
//currentServiceCenter.users = Array.isArray(currentServiceCenters.users) : [...currentServiceCenter.users, currentUser] : [currentUser]
currentServiceCenter.users.push(currentUser);
else{
currentServiceCenter.users = []
currentServiceCenter.users.push(currentUser);
}
},
removeAllServiceCenters() {
ServiceCenterService.deleteAllServiceCenters()
.then((response) => {
console.log(response.data);
this.refreshList();
})
.catch((e) => {
console.log(e);
});
},
searchId(id) {
ServiceCenterService.get(id)
.then((response) => {
this.currentServiceCenter = response.data;
})
.catch((e) => {
console.log(e);
});
this.refreshList();
// if(typeof id ==='string'){
// }
// else if(typeof id==='number'){
// CompanyService.get(id).then(response =>{
// this.currentCompany=response.data
// })
// .catch(e=>{
// console.log(e);
// });
// }
},
},
mounted() {
this.retrieveServiceCenters();
this.retrieveUsers();
},
computed:{
usersFilteredListByName(){
if(this.searchValue.trim().length >0){
return this.serviceCenters.filter((servicecenter) =>servicecenter.name.toLowerCase().includes(this.searchValue.trim()))
}
// if(this.searchValue.length>0 && isNaN(parseInt(this.searchValue))){
// return this.companies.filter((company) =>company.id.includes(this.searchValue))
// }
return this.serviceCenters
},
usersFilteredListById(){
if(this.searchValue.trim().length >0){
return this.serviceCenters.filter((servicecenter) =>servicecenter.id.toString().includes(this.searchValue))
}
return this.serviceCenters
},
}
};
</script>
You can ignore the rest of the functions and focus on the retrieve() and retrieveAllUsersByServiceCenterId(). Any help would be highly appreciated.

how to clear setTimeOut when component unmounts

i try to get Items data. if request response less than 1 i have to request again. so i write a recursive function with setTimeout. but when i try to change my route function keeps working. window.clearTimeout() or global.clearTimeOut() not worked here when component unmounts. Do i miss something?
useEffect(() => {
getItems(params);
return () => {
window.clearTimeout();
global.clearTimeout();
}
}, []);
const getItems = async(params) => {
try {
const { data = []} = await axios.get('/some-endpoint',params);
dispatch({ type: ITEMS_START });
if (data.length === 0) {
setTimeout(() => {
getItems(params);
}, 5000);
} else {
dispatch({ type: ITEMS_SUCCESS, payload: { data } });
}
} catch (error) {
dispatch({ type: ITEMS_ERROR, payload: error });
}
}
Use a ref to store the timeout ID and then clear that timeout.
const timeoutRef = React.useRef();
useEffect(() => {
getItems(params);
return () => {
window.clearTimeout(timeoutRef.current);
}
}, []);
const getItems = async(params) => {
try {
const { data = []} = await axios.get('/some-endpoint',params);
dispatch({ type: ITEMS_START });
if (data.length === 0) {
timeoutRef.current = setTimeout(() => {
getItems(params);
}, 5000);
} else {
dispatch({ type: ITEMS_SUCCESS, payload: { data } });
}
} catch (error) {
dispatch({ type: ITEMS_ERROR, payload: error });
}
}
Create a reference you can set your timeout too that the unmount can call back to.
let timeout = null;
useEffect(() => {
getItems();
return () => {
if(timeout)
clearTimeOut(timeout)
}
})
const getItems = () => {
timeout = setTimeOut(() => work, 5000);
}
This is the general idea.
Each SetTimeout ( and setInterval ) returns a number which can be used to clear it. ie, var x = setTimeout(() => console.log('timeout'),1000); clearTimeout(x); will do nothing.

Nativescript Vue - function is blocking DOM

I've got a nativescript vue application, and on a certain page I need to fetch some data (every 3 seconds) from an api using axios. The data is returned in xml, and I convert it to json using xml2js. I'm using async/await for both these functions. Something is blocking the UI thread, because whenever this function runs scrolling in my app freezes, along with any animations.
Does anyone know what here is blocking the DOM?
<template>
//ui code here
</template>
<script>
import { mapGetters } from 'vuex'
import axios from 'axios'
import xml2js from 'nativescript-xml2js'
export default {
name: 'component1',
data () {
return {
pending: true,
error: false,
results: null,
refreshInterval: null
}
},
computed: {
...mapGetters({
token: 'main/token'
})
},
methods: {
async requestData() {
const headers = {
Cookie: 'USER_ID=' + this.token
}
const url = 'url goes here'
const parser = new xml2js.Parser({
async: true
})
try {
const response = await axios.get(url, { headers: headers })
const newData = await new Promise((resolve, reject) => parser.parseString(response.data, (err, result) => {
if (err) reject(err)
else resolve(result)
}))
this.results = newData['results']
this.error = false
this.pending = false
} catch (e) {
this.data = null
this.error = e
this.pending = false
}
this.pending = false
}
},
created() {
setTimeout(() => {
this.requestData()
},500)
this.refreshInterval = setInterval(() => {
this.requestData()
},3000)
},
beforeDestroy () {
clearInterval(this.refreshInterval)
}
}
</script>
EDIT:
I tried implementing workers to offload xml2js to another thread, but still having the same issue. This is how my code looks now:
home.vue:
<template>
<template/>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'component1',
data () {
return {
dataLoaded: true,
error: false,
results: null,
refreshInterval: null
}
},
computed: {
...mapGetters({
token: 'main/token'
})
},
methods: {
requestData() {
console.log('fetching....')
this.$backendService
.api()
.then(xml => {
return this.$backendService.x2jworker(xml)
})
.then(json => {
if( this.results !== json['results'] ) {
this.results = json['results']
}
this.dataLoaded = true
this.error = false
})
.catch((error) => {
this.dataLoaded = true
this.error = true
})
}
},
created() {
setTimeout(() => {
this.requestData()
},500)
this.refreshInterval = setInterval(() => {
this.requestData()
},3000)
},
beforeDestroy () {
clearInterval(this.refreshInterval)
}
}
</script>
backend-service.js:
import axios from 'axios';
import xml2js from 'nativescript-xml2js'
import { WorkerService } from "../worker.service"
export default class BackendService {
api() {
return new Promise((resolve, reject) => {
const url = 'url'
axios.get(url)
.then(response => {
resolve(response.data)
})
.catch((error) => {
if (error) {
console.log('uh oh')
reject(error)
}
})
})
}
x2jworker(xml) {
return new Promise((resolve, reject) => {
var workerService = new WorkerService()
var jsWorker = workerService.initJsWorker()
jsWorker.onmessage = m => {
resolve(m.data)
}
jsWorker.postMessage(xml)
jsWorker.onerror = e => {
console.log(e)
jsWorker.terminate()
reject(e)
}
})
}
}
worker/javascript.worker.js:
import 'tns-core-modules/globals'
import xml2js from 'nativescript-xml2js'
global.onmessage = function (msg) {
console.log("Inside JS worker...")
var parser = new xml2js.Parser({
async: true
})
parser.parseString(msg.data, function (err, result) {
if (err) {
console.log(err)
global.close()
} else {
global.postMessage(result)
}
})
}
worker-service.js:
const workers = []
export class WorkerService {
constructor() {
}
initJsWorker() {
if (this.jsWorker) {
return this.jsWorker
}
const JsWorker = require("nativescript-worker-loader!./workers/javascript.worker.js")
this.jsWorker = new JsWorker()
workers.push(this.jsWorker)
return this.jsWorker
}
}
if ((module).hot) {
(module).hot.dispose(() => {
workers.forEach(w => {
w.terminate()
})
})
}

How to check meteor.call method ran successfully?

I am using meteor/react. I have two components. I want to pass method from one:
saveNewUsername(newUsername) {
Meteor.call('setNewUsername', newUsername, (error) => {
if(error) {
Materialize.toast(error.reason, 4000);
} else {
Materialize.toast('Username changed!', 4000);
}
});
}
And than I need to check it for success:
handleSaveOption() {
const { howToChangeOption } = this.props;
const optionValue = this.option.value.trim();
if(howToChangeOption(optionValue)) {
this.setState((prevState) => ({
startToChange: !prevState.startToChange,
}));
}
}
So, how to check Meteor.call for success and return true or false? Thanks!
Solved with promises. Maybe anyone has better solution?
saveNewUsername(newUsername) {
return new Promise((resolve, reject) => {
Meteor.call('setNewUsername', newUsername, (error) => {
if(error) {
Materialize.toast(error.reason, 4000);
reject();
} else {
Materialize.toast('Username changed!', 4000);
resolve();
}
});
});
}
handleSaveOption() {
const { howToChangeOption } = this.props;
const optionValue = this.option.value.trim();
howToChangeOption(optionValue).then(() => {
this.setState((prevState) => ({
startToChange: !prevState.startToChange,
}));
});
}

Categories

Resources