WebSockets server receives data but doesn't send back response - javascript

WebSocket doesn't send back a response despite the payLoad of the response is correct. The connection between front end and back end seems fine too. The boolean toggling inside the object array also works fine and does it's job. Any ideas why it isnt sending the JSON back to front end?
--------------------Front-end--------------------
const clientChangeVote = (c) => {
const payLoad = {
method: "changeVote",
clientId: gameData.clients[c].id,
gameId: gameData.id,
};
// voteValue: gameData.clients[c].voteReady,
ws.send(JSON.stringify(payLoad));
};
-----------------Back-end------------------------
if (result.method === "changeVote") {
const gameId = result.gameId;
const clientId = result.clientId;
games[gameId].clients
.filter((x) => x.id === clientId)
.forEach((vote) => (vote.voteReady = !vote.voteReady));
const updatedData = games[gameId].clients;
const payLoad = {
method: "changeVote",
updatedData: updatedData,
};
const game = games[gameId];
console.log(games);
game.clients.forEach((c) => {
console.log(payLoad);
c.connection.send(JSON.stringify(payLoad, getCircularReplacer()));
});
}
function getCircularReplacer() {
const seen = new WeakSet();
return (key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
}
-----------Inside the respone area. Im using React-----------
const [ws, setWs] = useState(new W3CWebSocket(URL));
useEffect(() => {
ws.onopen = () => {
console.log("Successful connection");
};
ws.onmessage = (message) => {
if (response.method === "changeVote") {
console.log("Vote received");
}
return () => {
ws.onclose = () => {
console.log("Connection closed");
setWs(new WebSocket(URL));
};
};
}, [ws.onmessage, ws.onopen, ws.onclose]);

Change ws.onmessage() :
ws.onmessage = (message) => {
let response = JSON.parse(message.data)
if (response.method === "changeVote") {
console.log("Vote received");
}
if not works add a comment.

Related

Message Unable to show automatically in reciever's side with Socket.io

I'm trying to send real time message with socket.io.
But the problem is that The reciever won't receive the message until i refresh the browser.
i'm getting all the data on the console but not in recievers end
I want to make it a real time message
Below are my codes
Messenger FrontEnd
// Context State
const { friends, setFriends, message, setMessage, authInfo } = useAuth();
const [currentFriend, setCurrentFriend] = useState("");
const [activeUser, setActiveUser] = useState([]);
const [newMessage, setNewMessage] = useState("");
const [socketMessage, setSocketMessage] = useState("");
const { updateNotification } = useNotification();
useEffect(() => {
socket.current = io("ws://localhost:9000");
socket.current.on("getMessage", (data) => {
setSocketMessage(data);
});
}, []);
useEffect(() => {
if (socketMessage && currentFriend) {
if (
socketMessage.senderId === currentFriend._id &&
socketMessage.receiverId === authInfo.profile.id
) {
console.log([...message, socketMessage]); // I'm confused on what to do here
}
}
setSocketMessage("");
}, [socketMessage]);
Socket.io Backend
let users = [];
const addUser = (userId, socketId, userInfo) => {
const checkUser = users.some((u) => u.userId === userId);
if (!checkUser) {
users.push({ userId, socketId, userInfo });
}
};
const userRemove = (socketId) => {
users = users.filter((u) => u.socketId !== socketId);
};
const findFriend = (id) => {
return users.find((u) => u.userId === id);
};
io.on("connection", (socket) => {
console.log("Socket Is Connecting...");
socket.on("addUser", (userId, userInfo) => {
addUser(userId, socket.id, userInfo);
io.emit("getUser", users);
});
socket.on("sendMessage", (data) => {
const user = findFriend(data.receiverId);
if (user !== undefined) {
socket.to(user.socketId).emit("getMessage", {
senderId: data.senderId,
senderName: data.senderName,
receiverId: data.receiverId,
createAt: data.time,
message: {
text: data.message.text,
image: data.message.image,
},
});
}
});

How to skip undefined/missing values in key-value pairs

I'm trying to build a citation generator from json in an API with data about images, stored in key-value pairs. I can get the data to return to the screen, but it always includes undefined in the citation. Sample manifest returns undefined as the creator since that isn't listed in this particular record. How can I keep any undefined value from being returned? I've tried changing the forEach to map, filtering at allMetadata by string length, using if !== undefined at insertCitation, and versions of those in different spots in the code.
EDIT: updated to provide full code, including print to page
(function () {
'use strict';
const buildCitation = {
buildMetadataObject: async function (collAlias, itemID) {
let response = await fetch('/iiif/info/' + collAlias + '/' + itemID + '/manifest.json');
let data = await response.json()
let allMetadata = data.metadata
let citationData = {};
allMetadata.forEach(function (kvpair) {
if (kvpair.value == undefined) {
return false;
} else if (kvpair.label === 'Title') {
citationData.itemTitle = kvpair.value;
} else if (kvpair.label === 'Creator') {
citationData.itemCreator = kvpair.value;
} else if (kvpair.label === 'Repository') {
citationData.itemRepository = kvpair.value;
} else if (kvpair.label === 'Collection Name') {
citationData.itemCollection = kvpair.value;
} else if (kvpair.label === 'Owning Institution') {
citationData.itemOwning = kvpair.value;
} else if (kvpair.label === 'Date') {
citationData.itemDate = kvpair.value;
} else if (kvpair.label === 'Storage Location') {
citationData.itemStorage = kvpair.value;
}
return true;
});
return citationData;
},
insertCitation: function (data) {
var testTitle = data.itemTitle;
console.log(testTitle);
const itemCite = `Citation: "${data.itemTitle}," ${data.itemDate}, ${data.itemCreator}, ${data.itemCollection}, ${data.itemOwning}, ${data.itemStorage}, ${data.itemRepository}.`;
const citationContainer = document.createElement('div');
citationContainer.id = 'citation';
citationContainer.innerHTML = itemCite;
// CHANGED to innerHTML instead of innerText because you may want to format it at some point as HTML code.
if (testTitle) {
document.querySelector('.ItemView-itemViewContainer').appendChild(citationContainer);
}
}
}
document.addEventListener('cdm-item-page:ready', async function (e) {
const citationData = await buildCitation.buildMetadataObject(e.detail.collectionId, e.detail.itemId);
console.log({ citationData });
buildCitation.insertCitation(citationData);
});
document.addEventListener('cdm-item-page:update', async function (e) {
document.getElementById('citation').remove();
const citationData = await buildCitation.buildMetadataObject(e.detail.collectionId, e.detail.itemId);
console.log({ citationData });
buildCitation.insertCitation(citationData);
});
})();
I've simplified your program. The undefined is coming from the fact that there is no item with label Date
const mappings = {
Date: 'itemDate',
Title: 'itemTitle',
Creator: 'itemCreator',
Repository: 'itemRepository',
'Storage Location': 'itemStorage',
'Owning Institution': 'itemOwning',
'Collection Name': 'itemCollection',
}
async function buildMetadataObject(collAlias, itemID) {
let response = await fetch('https://teva.contentdm.oclc.org/iiif/info/p15138coll25/1421/manifest.json');
let data = await response.json()
return data.metadata.reduce(
(acc, { label, value }) => ({ ...acc, [ mappings[label] ]: value }),
{}
)
}
function insertCitation(data) {
var testTitle = data.itemTitle;
const fieldBlackList = ['itemTitle'];
const itemCite = `Citation: "${data.itemTitle}," ${
Object.values(mappings).reduce((acc, cur) => {
if (fieldBlackList.includes(cur)) return acc;
const value = data[cur];
return value ? [...acc, value] : acc
}, []).join(', ')
}.`;
console.log(itemCite);
}
//MAIN PROGRAM
(async() => {
const citationData = await buildMetadataObject();
insertCitation(citationData);
})()

Why forkJoin is returning a wrong value from my observables?

I have an application that is using Firebase Storage to send some image data, so I'm using this method:
startUpload() {
if (typeof this.fileList !== 'undefined' && this.fileList.length > 0) {
const observableList = [];
for (let i = 0; i < this.fileList.length; i++) {
// The storage path
const path = this.userModel.companyCode + `/${new Date().getTime()}_${this.fileList[i].name}`;
// Totally optional metadata
const customMetadata = {
app: 'My AngularFire-powered PWA!'
};
const fileRef = this.storage.ref(path);
// The main task
this.task = this.storage.upload(path, this.fileList[i], {
customMetadata
});
// Progress monitoring
this.percentage = this.task.percentageChanges();
this.snapshot = this.task.snapshotChanges();
// The file's download URL
observableList.push(
this.task.snapshotChanges().pipe(
finalize(async () => {
return await fileRef.getDownloadURL();
}))
);
// observableList = this.task.snapshotChanges();
// observableList.push(taskObservable);
}
console.log(observableList);
forkJoin(
observableList
).subscribe(
response => {
console.log(response);
}
);
}
}
This part:
this.task.snapshotChanges().pipe(
finalize(async () => {
return await fileRef.getDownloadURL();
}))
When I'm using this function alone and using like this:
this.task.snapshotChanges().pipe(
finalize(async () => {
this.downloadUrl = await fileRef.getDownloadURL().toPromise;
}))
They return the right URL, this.downloadUrl is a global variable that is downloadURL: Observable;
But I don't want to return one by one I want the 3 results, so I have an idea to use forkJoin that is like Promise.All() from promise in javascript:
console.log(observableList);
forkJoin(
observableList
).subscribe(
response => {
console.log(response);
}
);
And I'm getting this in the console:
(3) [UploadTaskSnapshot, UploadTaskSnapshot, UploadTaskSnapshot]
How I can get the download URL from them?
finalize takes a callback function of return type void. That's why it worked in your case for handling individually, but not when you tried to return something.
finalize-rxjs
I think the below code should work for you
startUpload() {
if (typeof this.fileList !== "undefined" && this.fileList.length > 0) {
const observableList = [];
const fileRefList = [];
this.fileList.forEach(file => {
const path =
this.userModel.companyCode + `/${new Date().getTime()}_${file.name}`; // Totally optional metadata
const customMetadata = { app: "My AngularFire-powered PWA!" };
fileRefList.push(this.storage.ref(path)); // The main task
this.task = this.storage.upload(path, file, {
customMetadata
}); // Progress monitoring
this.percentage = this.task.percentageChanges();
this.snapshot = this.task.snapshotChanges();
observableList.push(this.snapshot);
});
console.log(observableList);
forkJoin(observableList)
.pipe(map(async (_, i) => await fileRefList[i].getDownloadURL()))
.subscribe(response => console.log(response));
}
}

How to delete a key/value inside value field with Dexie.js?

I have a row with value like this below:
{
"id": 1,
"token": "abcd"
}
How do I delete and save the value without "token" so it becomes this?
{
"id": 1
}
Do I need to first get the object, modify it then save back?
Maybe this will help you:
function patch(db, id, delta) {
return new Promise((resolve, reject) => {
const tx = db.transaction('mystore', 'readwrite');
tx.onerror = (event) => reject(event.target.error);
tx.oncomplete = () => resolve();
const store = tx.objectStore('mystore');
const request = store.get(id);
request.onsuccess = (event) => {
const object = event.target.result;
if (!object) {
reject(new Error(`No matching object for ${id}`));
return;
}
for (const prop in delta) {
if (typeof delta[prop] === 'undefined') {
delete object[prop];
} else {
object[prop] = delta[prop];
}
}
store.put(object);
};
});
}
async function dostuff() {
let db;
const id = 1;
const delta = {
token: undefined
};
try {
db = await connect();
await patch(db, id, delta);
} finally {
if (db) {
db.close();
}
}
}

Can't figure out why my app.get is being run twice?

I have a app.get which inside of it is quite a bit of logic. Which everything works great aside from some of the logic being called twice for some reason. I have noticed when I was saving something to by db that it would save two rows.
So I put a console.log in that area and sure enough it was logging it twice.
Any reason why this is happening?
app.get('/shopify/callback', (req, res) => {
const { shop, hmac, code, state } = req.query;
const stateCookie = cookie.parse(req.headers.cookie).state;
if (state !== stateCookie) {
return res.status(403).send('Request origin cannot be verified');
}
if (shop && hmac && code) {
// DONE: Validate request is from Shopify
const map = Object.assign({}, req.query);
delete map['signature'];
delete map['hmac'];
const message = querystring.stringify(map);
const providedHmac = Buffer.from(hmac, 'utf-8');
const generatedHash = Buffer.from(
crypto
.createHmac('sha256', config.oauth.client_secret)
.update(message)
.digest('hex'),
'utf-8'
);
let hashEquals = false;
try {
hashEquals = crypto.timingSafeEqual(generatedHash, providedHmac)
} catch (e) {
hashEquals = false;
};
if (!hashEquals) {
return res.status(400).send('HMAC validation failed');
}
// DONE: Exchange temporary code for a permanent access token
const accessTokenRequestUrl = 'https://' + shop + '/admin/oauth/access_token';
const accessTokenPayload = {
client_id: config.oauth.api_key,
client_secret: config.oauth.client_secret,
code,
};
request.post(accessTokenRequestUrl, { json: accessTokenPayload })
.then((accessTokenResponse) => {
const accessToken = accessTokenResponse.access_token;
// DONE: Use access token to make API call to 'shop' endpoint
const shopRequestUrl = 'https://' + shop + '/admin/shop.json';
const shopRequestHeaders = {
'X-Shopify-Access-Token': accessToken,
}
request.get(shopRequestUrl, { headers: shopRequestHeaders })
.then((shopResponse) => {
const response = JSON.parse(shopResponse);
const shopData = response.shop;
console.log('BEING CALLED TWICE...')
res.render('pages/brand_signup',{
shop: shopData.name
})
})
.catch((error) => {
res.status(error.statusCode).send(error.error.error_description);
});
})
.catch((error) => {
res.status(error.statusCode).send(error.error.error_description);
});
} else {
res.status(400).send('Required parameters missing');
}
});

Categories