Trying to send params to axios in get - react - javascript

I'm new here on the site, and new to React.
I built a function that works great in nodejs. There are rare cases where I want to run this function according to the parameters I send it to, so I try to send it the parameters but I think I can not, I try to print it - and I do not get a print of the parameters I want to send.
i run the function throw click at buttom in react:
<Button onClick={() => {
const result = [1,2,3,4,5,"test"];
props.makeMatchVer2(result);
}}>
make match ver2
</Button>
the action I'm run in axios:
export const makeMatchVer2 = (data) => (dispatch) => {
dispatch({ type: LOADING_DATA });
axios
.get('/kmeans', {
params: {
filterArray: data
}
})
.then((res) => {
dispatch({
type: MAKE_MATCH,
payload: res.data
});
})
.catch((err) => {
dispatch({
type: MAKE_MATCH,
payload: []
});
});
};
the function I'm build in nodeJS:
exports.addUserKmeansMatch = (req, res) => {
console.log("addUserKmeansMatch function start:");
console.log(req.data);
if(req.params)
{
console.log(req.params);
}
let userIndex = 0;
let engineers = [];
let engineersHandles = [];
let engineerDetailsNumeric = {};
db.collection("preferences").get().then(querySnapshot => {
querySnapshot.forEach(doc => {
const engineerDetails = doc.data();
if (engineerDetails.handle === req.user.handle) {
engineersHandles.unshift(engineerDetails.handle);
delete engineerDetails.handle;
engineerDetailsNumeric = convertObjectWithStrToNumber(engineerDetails);
engineers.unshift(engineerDetailsNumeric);
}
else {
engineersHandles.push(engineerDetails.handle);
delete engineerDetails.handle;
engineerDetailsNumeric = convertObjectWithStrToNumber(engineerDetails);
engineers.push(engineerDetailsNumeric);
}
});
kmeans.clusterize(engineers, { k: 4, maxIterations: 5, debug: true }, (err, result) => {
if (err) {
console.error(err);
return res.status(500).json({ error: err.code });
} else {
const cluster = result.clusters;
let foundedMatches = GetUserSerialGroup(userIndex, [...cluster], [...engineers]);
let foundedMatchesHandle = GetUserSerialGroupHandle(userIndex, [...cluster], [...engineersHandles]);
let totalTest = {
foundedMatches: foundedMatches,
foundedMatchesHandle: foundedMatchesHandle,
cluster: cluster,
engineersHandles: engineersHandles,
engineers: engineers
};
let userMatchHandle = reduceUserMatchHandle(foundedMatchesHandle);
userMatchHandle.handle = req.user.handle;
db.doc(`/match/${req.user.handle}`)
.set(userMatchHandle)
.then(() => {
return res.json({ message: "Details added successfully" });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
}
})
})
};
Through the button, I send parameters to the function, but I do not see their print, probably something does not work, but I do not know why, I'm new to it

makeMatchVer2 is a thunk. You should call it with dispatch: dispatch(props.makeMatchVer2(result))

The code is correct, I accidentally sent the wrong object, I have 2 objects with almost identical names, one array and the other an object. And I accidentally sent the object instead of the array, it's working right now, thank you.

Related

Broadcasting to all clients with Deno websocket

I want to add notifications to an application I've developed.
Unfortunately, Deno has removed the ws package.(https://deno.land/std#0.110.0/ws/mod.ts)
That's why I'm using the websocket inside the denon itself. Since it doesn't have many functions, I have to add some things myself.
For example, sending all messages to open clients.
What I want to do is when the pdf is created, a (data, message) comes from the socket and update the notifications on the page according to the incoming data.
I keep all open clients in a Map. and when the pdf is created, I return this Map and send it to all sockets (data, message).
However, this works for one time.
server conf...
import {
path,
paths,
ctid,
} from "../deps.ts";
const users = new Map();
const sockets = new Map()
const userArr = [];
export const startNotif = (socket,req) => {
const claims = req.get("claims");
const org = req.get("org");
claims.org = org;
console.log("connected")
users.set(claims.sub, {"username":claims.sub,"socket":socket})
users.forEach((user)=>{
if(userArr.length === 0){
userArr.push(user)
}
else if(userArr.every((w)=> w.username !== user.username) )
userArr.push(user)
})
sockets.set(org, userArr)
function broadcastMessage(message) {
sockets.get(org).map((u)=>{
console.log(u.socket.readyState)
u.socket.send(message)
})
}
if (socket.readyState === 3) {
sockets.delete(uid)
return
}
const init = (msg) => {
socket.send(
JSON.stringify({
status: "creating",
})
);
};
const ondata = async (msg) => {
const upfilepath = path.join(paths.work, `CT_${msg.sid}_report.pdf`);
try {
const s=await Deno.readTextFile(upfilepath);
if(s){
socket.send(
JSON.stringify({
status: "end",
})
);
} else {
socket.send(
JSON.stringify({
status: "creating",
})
);
}
} catch(e) {
if(e instanceof Deno.errors.NotFound)
console.error('file does not exists');
}
};
const end = () => {
try {
const endTime = Date.now()
const msg = "Your PDF has been created"
const id = ctid(12) // random id create
broadcastMessage(
JSON.stringify({
id: id,
date: endTime,
status: "done",
message: msg,
read: 'negative',
action: 'pdf'
})
);
} catch (e) {
console.log(400, "Cannot send.", e);
}
}
socket.onmessage = async (e) => {
const cmd = JSON.parse(e.data);
if(cmd.bid === 'start'){
await init(cmd)
}
if(!cmd.bid && cmd.sid){
await ondata(cmd)
}
if(cmd.bid === 'end'){
await end();
}
}
socket.onerror = (e) => {
console.log(e);
};
}
client conf...
export const webSocketHandler = (request) =>
new Promise((res, rej) => {
let url;
if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') {
url = `http://localhost:8080/api/notifications/ws`.replace('http', 'ws');
} else {
url = `${window.location.origin}/api/notifications/ws`.replace('http', 'ws');
}
const token = JSON.parse(sessionStorage.getItem('token'));
const orgname = localStorage.getItem('orgname');
const protocol = `${token}_org_${orgname}`;
const socket = new WebSocket(url, protocol);
const response = Object.create({});
socket.onopen = function () {
socket.send(
JSON.stringify({
bid: 'start',
})
);
};
socket.onmessage = function (event) {
response.data = JSON.parse(event.data);
if (response.data.status === 'creating') {
socket.send(
JSON.stringify({
sid: request.sid,
})
);
} else if (response.data.status === 'end') {
socket.send(
JSON.stringify({
bid: 'end',
})
);
} else if (response.data.status === 'done') {
try {
res(response);
} catch (err) {
rej(err);
}
}
};
socket.onclose = function (event) {
response.state = event.returnValue;
};
socket.onerror = function (error) {
rej(error);
};
});
onclick function of button I use in component...
const donwloadReport = async (type) => {
const query = `?sid=${sid}&reportType=${type}`;
const fileName = `CT_${sid}_report.${type}`;
try {
type === 'pdf' && setLoading(true);
const response = await getScanReportAction(query);
const request = {
sid,
};
webSocketHandler(request)
.then((data) => {
console.log(data);
dispatch({
type: 'update',
data: {
id: data.data.id,
date: data.data.date,
message: data.data.message,
action: data.data.action,
read: data.data.read,
},
});
})
.catch((err) => {
console.log(err);
});
if (type === 'html') {
downloadText(response.data, fileName);
} else {
const blobUrl = await readStream(response.data);
setLoading(false);
downloadURL(blobUrl, fileName);
}
} catch (err) {
displayMessage(err.message);
}
};
Everything works perfectly the first time. When I press the download button for the pdf, the socket works, then a data is returned and I update the notification count with the context I applied according to this data.
Later I realized that this works in a single tab. When I open a new client in the side tab, my notification count does not increase. For this, I wanted to keep all sockets in Map and return them all and send a message to each socket separately. But in this case, when I press the download button for the second time, no data comes from the socket.
Actually, I think that I should do the socket initialization process on the client in the context. When you do this, it starts the socket 2 times in a meaningless way.
In summary, consider an application with organizations and users belonging to those organizations. If the clients of A, B, C users belonging to X organization are open at the same time and user A pressed a pdf download button, I want A, B, C users to be notified when the pdf is downloaded.
I would be very grateful if someone could show me a way around this issue.
Have you looked at the BroadcastChannel API? Maybe that could solve your issue. See for example:
Deno specific: https://medium.com/deno-the-complete-reference/broadcast-channel-in-deno-f76a0b8893f5
Web/Browser API: https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API

Called two functions on route watch change in vuejs

As I am new in Vuejs, It will be very easy for others, but for me I cannot get it right, I search a lot but cannot get the expected answer
Below is my code
watch: {
$route () {
this.newsData = []
this.loadNewsByCategory()
this.category = {}
this.getCategoryData()
}
},
created () {
this.getCategoryData()
this.loadNewsByCategory()
},
methods () {
async getCategoryData() {
// console.log('called category data')
try {
await firebase.firestore().collection('categories').doc(this.$route.params.id).get().then((doc) => {
if (doc.exists) {
this.category = doc.data()
}
})
} catch (error) {
console.log(error) // this line show the error I've post below
this.$q.notify({ type: 'negative', message: error.toString() })
}
},
async loadNewsByCategory() {
// console.log('load news')
try {
var db = firebase.firestore()
var first = db.collection('posts')
.where('publishedAt', '<=', new Date())
.where('categories', 'array-contains', this.$route.params.id)
.orderBy('publishedAt', 'desc')
.limit(12)
return await first.get().then((documentSnapshots) => {
documentSnapshots.forEach((doc) => {
const news = {
id: doc.id,
slug: doc.data().slug,
title: doc.data().title,
image: doc.data().image.originalUrl,
publishedAt: dateFormat(doc.data().publishedAt.toDate(), 'dS mmm, yyyy')
}
this.newsData.push(news)
})
this.lastVisible = documentSnapshots.docs[documentSnapshots.docs.length - 1]
})
} catch (error) {
this.$q.notify({ type: 'negative', message: error.toString() })
}
}
}
In my code, when initialize I call two functions to query data from firebase and it's working as expected. but when the route change for example: from getdata/1 to getdata/2 one function i.e., loadNewsByCategory() is working but others throw error like below
TypeError: u.indexOf is not a function
at VueComponent.getCategoryData (getdata.vue?3b03:102)
at VueComponent.created (getdata.vue?3b03:92)
Thank you in advance

Wait for server response with axios from different file React

I have a loop. On each round I need to add Question data into MongoDB database. This works fine. However, I want to get _id of the new inserted Question before the loop goes into the next round. This is where I have a problem. It takes certain amount of time before the server returns _id and loop goes to the next round by that time. Therefore, I need a way to wait for the server response and only after that move to the next round of the loop.
Here is my back-end code:
router.post("/createQuestion", (req, res) => {
const newQuestion = new Question({
description: req.body.description,
type: req.body.type,
model: req.body.model
});
newQuestion.save().then(question => res.json(question._id))
.catch(err => console.log(err));
});
Here is my axios function, which is in a separate file and imported into the class:
export const createQuestion = (questionData) => dispatch => {
axios.post("/api/scorecard/createQuestion", questionData)
.then(res => {
return res.data;
}).catch(err =>
console.log("Error adding a question")
);
};
Here is my code inside my class:
JSON.parse(localStorage.getItem(i)).map(question => {
const newQuestion = {
description: question.description,
type: question.questionType,
model: this.props.model
}
const question_id = this.props.createQuestion(newQuestion);
console.log(question_id);
}
Console shows undefined.
i faced the same issue i solved the same by sending the array question to the node and read one by one question and update with the next Question ID.
router.post("/createQuestion", (req, res) => {
let d =[questionarray];
let i = 0;
let length = d.length;
var result = [];
try {
const timeoutPromise = (timeout) => new Promise((resolve) => setTimeout(resolve, timeout));
for (i = 0; i < length; i++) {
await timeoutPromise(1000); // 1000 = 1 second
let CAT_ID = parseInt(d[i].CAT_ID);
let TOPIC_ID = parseInt(d[i].TOPIC_ID);
let Q_DESC = (d[i].Q_DESC);
let OPT_1 = (d[i].OPT_1);
let OPT_2 = (d[i].OPT_2);
let OPT_3 = (d[i].OPT_3);
let OPT_4 = (d[i].OPT_4);
let ANS_ID = (d[i].ANS_ID);
let TAGS = (d[i].TAGS);
let HINT = (d[i].HINT);
let LEVEL = d[i].LEVEL;
let SRNO = d[i].SrNo;
let qid;
const savemyData = async (data) => {
return await data.save()
}
var myResult = await Question.find({ TOPIC_ID: TOPIC_ID }).countDocuments(function (err, count) {
if (err) {
console.log(err);
}
else {
if (count === 0) {
qid = TOPIC_ID + '' + 10001;
const newQuestion = new Question({
Q_ID: qid,
CAT_ID: CAT_ID,
TOPIC_ID: TOPIC_ID,
Q_ID: qid,
Q_DESC: Q_DESC,
OPT_1: OPT_1,
OPT_2: OPT_2,
OPT_3: OPT_3,
OPT_4: OPT_4,
ANS_ID: ANS_ID,
HINT: HINT,
TAGS: TAGS,
LEVEL: LEVEL,
Q_IMAGE: ''
})
await savemyData(newQuestion)
.then(result => { return true })
.catch(err => { return false });
//`${SRNO} is added successfully`
//`${SRNO} is Failed`
}
else if (count > 0) {
// console.log(count)
Question.find({ TOPIC_ID: TOPIC_ID }).sort({ Q_ID: -1 }).limit(1)
.then(question => {
qid = question[0].Q_ID + 1;
const newQuestion = new Question({
Q_ID: qid,
CAT_ID: CAT_ID,
TOPIC_ID: TOPIC_ID,
Q_ID: qid,
Q_DESC: Q_DESC,
OPT_1: OPT_1,
OPT_2: OPT_2,
OPT_3: OPT_3,
OPT_4: OPT_4,
ANS_ID: ANS_ID,
HINT: HINT,
TAGS: TAGS,
LEVEL: LEVEL,
Q_IMAGE: ''
})
await savemyData(newQuestion)
.then(result => { return true })
.catch(err => { return false });
})
.catch(err => console.log(err));
}
}
});
if (myResult)
result.push(`${SRNO} is added successfully`);
else
result.push(`${SRNO} is Failed`);
}
// console.log(result)
return res.json(result);
}
catch (err) {
//res.status(404).json({ success: false })
console.log(err)
}
});
First your function createQuestion doesn't return a value so the assigning to question_id would always be undefined. Anyways, since u have a dispatch in your createQuestion function, I am assuming u r using redux, so I would suggest you to using redux-thnk, split the fetching new action logic to a thunk action, and use the questionID value from the redux state rather than returning a value from createQuestion. In your class u can be listening for a change of the questionID and if that happens, dispatch the saving of the next question.

How to use promise and loop over mongoose collection

I'm making chat inside my website. To store data I use Chat, User, Messages collections.
I want results to be in Array containing:
[{
username (another one, not me)
last update
last message
}]
In Chat model I have only chatid and array of two members, so I need to loop through User collection to get user name using user id from it. I want to save in array all names (in future I would also like to loop through messages to get latest messages for each chatid). Issue is that when I return chatsList it is empty. I think I need somehow to use Promise, but I'm not completely sure how it should work.
Chat.find({ members: userId })
.then(chats => {
let chatsList = [];
chats.forEach((chat, i) => {
let guestId = chat.members[1 - chat.members.indexOf(userId)];
User.findOne({ _id: guestId })
.then(guest => {
let chatObj = {};
name = guest.name;
chatsList.push(name);
console.log("chatsList", chatsList)
})
.catch(err => console.log("guest err =>", err))
})
return res.json(chatsList)
})
.catch(err => {
errors.books = "There are no chats for this user";
res.status(400).json(errors);
})
Indeed, Promise.all is what you are looking for:
Chat.find({ members: userId })
.then(chats => {
let userPromises = [];
chats.forEach((chat, i) => {
let guestId = chat.members[1 - chat.members.indexOf(userId)];
userPromises.push(User.findOne({ _id: guestId }));
});
return Promise.all(userPromises).then(guests => {
let chatsList = [];
guests.forEach(guest => {
chatsList.push(guest.name);
});
return res.json(chatsList);
});
});
});
although it would probably be better to do a single call to DB with a list of ids ($in query). Something like this:
Chat.find({ members: userId })
.then(chats => {
let ids = [];
chats.forEach((chat, i) => {
let guestId = chat.members[1 - chat.members.indexOf(userId)];
ids.push(guestId);
});
return User.find({_id: {$in: ids}}).then(guests => {
let chatsList = [];
guests.forEach(guest => {
chatsList.push(guest.name);
});
return res.json(chatsList);
});
});
});
You may want to additionally validate if every id had a corresponding guest.
You are running into concurrency issues. For example, running chats.forEach, and inside forEach running User.findOne().then: The return statement is already executed before the User.findOne() promise has resolved. That's why your list is empty.
You could get more readable and working code by using async/await:
async function getChatList() {
const chats = await Chat.find({members: userId});
const chatsList = [];
for (const chat of chats) {
let guestId = chat.members[1 - chat.members.indexOf(userId)];
const guest = await User.findOne({_id: guestId});
chatsList.push(guest.name);
}
return chatsList;
}
Then the code to actually send the chat list back to the user:
try {
return res.json(await getChatList());
} catch (err) {
// handle errors;
}
You can try this:
Chat.find({ members: userId }).then(chats => {
let guestHashMap = {};
chats.forEach(chat => {
let guestId = chat.members.filter(id => id != userId)[0];
// depending on if your ID is of type ObjectId('asdada')
// change it to guestHashMap[guestId.toString()] = true;
guestHashMap[guestId] = true;
})
return Promise.all(
// it is going to return unique guests
Object.keys(guestHashMap)
.map(guestId => {
// depending on if your ID is of type ObjectId('asdada')
// change it to User.findOne({ _id: guestHashMap[guestId] })
return User.findOne({ _id: guestId })
}))
})
.then(chats => {
console.log(chats.map(chat => chat.name))
res.json(chats.map(chat => chat.name))
})
.catch(err => {
errors.books = "There are no chats for this user";
res.status(400).json(errors);
})

Using only one API if another one does not have data

const getUser = async (user) => {
const body = await snekfetch.get('https://www.website.com/api/public/users?name=' + user);
const userInfo = JSON.parse(body.text);
const r = await snekfetch.get('https://www.website.com/api/public/users/' + userInfo.uniqueId + '/profile');
const extraUserInfo = JSON.parse(r.text);
const _message = await client.users.get('437502925019807744').send({ files: ['https://www.website.nl/avatar-imaging/avatarimage?figure=h' + userInfo.figureString + '.png'] });
const avatarImage = _message.attachments.first().url;
return { userInfo, extraUserInfo, avatarImage };
};
getUser(args[0]).then((result) => {
message.channel.send(`${result.userInfo.name}`);
}).catch(function(result) {
console.log(result.userInfo.name);
});
Here I am trying to use 3 API's, however it always goes to the catch, even if one exists and other don't, I tried to only use result.userInfo.name to only use the first API, also in the catch I use the first one, then I tried a name that only has the first API but not the second one however I still get: TypeError: Cannot read property 'name' of undefined because it looks at the second API as well, what else can I do to handle with this situation? So basically how can I only catch errors for the first API
edit: I also tried:
if (extraUserInfo.user.name) {return { userInfo, extraUserInfo, avatarImage };}
else {return { userInfo, avatarImage };}
Fixed it with a try catch
try {
const r = await snekfetch.get('https://www.website.com/api/public/users/' + userInfo.uniqueId + '/profile');
const extraUserInfo = JSON.parse(r.text);
return {
userInfo,
extraUserInfo,
avatarImage
};
} catch (error) {
const extraUserInfo = {
'error': 'not-found'
};
return {
userInfo,
extraUserInfo,
avatarImage
};
}
};
getUser(args[0]).then((result) => {
console.log(result.extraUserInfo.error === 'not-found' ? result.userInfo.name : result.extraUserInfo.user.name);
}).catch((error) => {
console.log(error);
});

Categories

Resources