I've been struggling with my app last days.
while communicating with the API all data (shown or not by the app) could be seen throught the requests console, so i decided to encrypt the data send by the API, and decrypt the encrypted data in the app directly, so the request doesn't have the "clear version" displayed.
apparently no problems to encrypt, but even tho decrypting works, it freezes the app for a decent time each time new data arrives, i've been tryng async, but it doesn't change anything.
(the data is an array filled with objects)
Here is the code of the update function :
const fetchData = (setter) => {
const encrypter = new Cryptr(process.env.NEXT_PUBLIC_ENCRYPT_KEY);
fetch(process.env.NEXT_PUBLIC_DATA_FETCHING_URL)
.then((response) => response.text())
.then((data) => {
const decryptData = new Promise((resolve, reject) => {
try {
console.info('Decrypting...');
let decryptedData = encrypter.decrypt(data);
console.info('Parsing...');
let parsedData = JSON.parse(decryptedData);
console.info('Data parsed !');
resolve(parsedData);
} catch {
reject('ERROR DURING DATA DECRYPTION');
}
})
.then((parsedData) => setter(parsedData))
.catch((err) => console.error(err));
});
};
As you can see, i'm usingthe cryptr module (6.0.3), the app is running on next.js (12.2.5).
I tested many things, including the freeze provenance, but it seems like it's the decryption (not the parse or the setter())
PS: The js setter() function is the setter of the state that contains data from the server.
Is there a way to handle those unwanted freezes ?
Thanks for helping me with this 😊
Related
I am coming across a 429 error while fetching a lot of urls at the same time, in useEffect. I am trying to fetch prices of stocks by mapping the names from the array shortNames using a proxy server called allorigins
The function that fetches the data:
const fetchData = async (url) => {
try {
const response = await fetch(url)
if (!response.ok) throw response.statusText
const data = response.json()
return data
} catch (error) {
console.error(error)
}
};
The price_response stores the price data in an array after the Promises are resolved:
const price_response = await Promise.all(shortNames.map((stock) =>
fetchData(`https://api.allorigins.win/raw?url=https://query1.finance.yahoo.com/v8/finance/chart/${stock}.BO`)
));
This async method of fetching throws error when it loads the first time. Refreshing the page adds more data to price_response retrieving some already fetched data from the disk-cache.
I am trying to find a better way, as to not make the user refresh the page again and again.
Is there a way I can fetch 60-70 urls using async or even sync function? Also, can I use disk-cache in a more customised way to make this work on the very first load?
I'm getting an image from a user and storing it with in Cloud Storage through Firebase. The storing works fine.
Right after that I'm requesting all images from the storage to display them, but I got the response without the last submit. So I need to refresh the page, then useEffect make one more request and everything works.
UPD. Here's the the complete logic:
This function is uploading image to the storage:
const uploadImage = async (image,imageName) => {
if (image == null) return;
const imageRef = ref(storage,`images/${imageName}`);
try {
uploadBytes(imageRef, image);
} catch (err) {
alert(`${err}`)
}
}
This function does request to firestore, but doesn't return last uploaded image every time, just randomly. sometimes it does, usually not :
const getImages = async () => {
try {
const imagesListData = await listAll(imagesListRef);
setImagesList([]);
imagesListData.items.forEach(item => {
getDownloadURL(item).then(url => setImagesList(prev => [...prev,url]));
})
} catch(err){
alert(err.message);
}
}
after refreshing the page, useEffect does the job :
useEffect(() => {
getImages();
},[])
As I said above sometimes it works as I expected from the first try without me changing the code(which is the most confusing),most of the times I need to refresh the page to get the last image.
p.s. list() instead listAll() give same results
So I have like 30k++ huge data from my firebase. The bad thing about it is, everytime I click back button on my React page, it fetches that 30k++ data again, it hurts the wallet.
Is there anything I can do to solve it?
this is the useEffect I use in my home page
useEffect(() => {
// first 5 posts
Form.allPosts()
.then((res) => {
setSalesLastMonth(res.posts);
setLastKey(res.lastKey);
})
.catch((err) => {
console.log(err);
});
Form.postsToday()
.then((res) => {
setSales(res.posts)
}).catch((err) => {
console.log(err)
})
}, []);
this is an example of the firebase function:
postsToday: async function () {
try {
const yesterday = new Date(new Date().setHours(0, 0, 0, 0));
let today = new Date();
const data = await firestore
.collectionGroup('form')
.orderBy("Created At", "desc")
.where('Created At', '>=', yesterday)
.where('Created At', '<=', today)
.get()
let posts = [];
let lastKey = "";
data.forEach((doc) => {
posts.push({
id: doc.id,
etc etc
});
lastKey = doc.data()['Created At']
});
return { posts, lastKey };
} catch (e) {
console.log(e);
}
},
Can someone help me?
The first thing to do is to enable Firestore's client-side persistence, which means that client will keep a disk-based cache that it can read documents from that it has seen recently.
Another way to reduce the reads is to only load the data the user sees. It seems unlikely that the user will check all 30K forms, so I'd recommend using cursors/queries to implement pagination or infinite scrolling to load only the first page of data initially, and load the rest on demand as needed. You seem to already be tracking the lastKey, which is the main thing you'll need for both.
Finally, also consider if each user needs to perform this query individually, or whether you can perform them once and share the results with all users. For example, you could create a data bundle for things that all users see, serve that bundle from a CDN, and then inject that into the offline cache.
async function play(message, correct, channel, mp3) {
const connection = await channel.join();
await new Promise(done => setTimeout(done, 1000));
let readStream = await fs.createReadStream(mp3);
await timerEventEmitter.emit("update", correct);
const dispatcher = await connection.play(readStream)
.on('end', () => {
console.log('Stream ended!');
})
.on('finish', () => {
console.log('Stream finished!');
})
.on('error', error => {
console.error(error);
});
timerEventEmitter.on('end', (time) => {
dispatcher.destroy();
})
}
This might be a big or small issue, I hope it's the latter but it's most likely the former. My bot is supposed to play audio in a voice chat and it works perfectly fine in one server.
However, when I try playing audio at the same time in two different servers, the audio does some weird stuff. The audio cuts out and ends in one server while playing the other audio in the other server.
Below is the code from above that I use to play the audio. I'm not really getting an error but I do need maybe an explanation or a solution if I want to add this bot to multiple servers. I'm sure there's a good explanation; hopefully it doesn't require a rework.
Also, it's not a bad connection issue either as I tried it on localhost and replit, and they both had that same issue.
let readStream = await fs.createReadStream(mp3);
const dispatcher = await connection.play(readStream);
I want to build a CRUD in React with Laravel and Firebase. Everything is perfect when I'm working with text, but I got trouble when I try to upload an image to Firebase Storage. I can save it but I can't get its URL.
I wrote 2 "console.log". In the first one the URL is there, but the second one (when I try to get the URL from the state variable) doesn't return anything.
handleSubmit = event =>{
event.preventDefault();
const {imagen} = this.state;
if(imagen!=null){
const uploadTask = storage.ref(`imagenes/${imagen.name}`).put(imagen);
uploadTask.on('state_changed',
(snapshot) => {
const progress = Math.round((snapshot.bytesTransferred / snapshot.totalBytes) * 100);
this.setState({progress});
},
(error) => {
console.log(error);
},
() => {
storage.ref('imagenes').child(imagen.name).getDownloadURL().then(url => {
this.setState({url});
console.log(this.state.url); //<<<<<<<<<<<<<SHOW URL (IT'S OK!)
})
});
}
var direccion = null;
const form = event.target;
let data = new FormData(form);
data.append('url', this.state.url);
console.log(this.state.url); //<<<<<<<DOESN'T SHOW URL !! (HERE'S THE TROUBLE)
If you want to check the entire file:
https://github.com/AndresVasquezPUCE/project/blob/master/pelicula
I'm not a professional, so please don't be rude :D
this.setState is asynchronous
If you want to get the updated state value, add a callback and access the new state there like
this.setState({ url: 'some url'}, () => {
conosle.log(this.state.url);
});
Data is loaded from Firebase asynchronously. By the time your console.log(this.state.url); //<<<<<<<DOESN'T SHOW URL !! (HERE'S THE TROUBLE) the data hasn't been loaded from Firebase yet, and the then hasn't been called yet.
Any code that needs the data from Firebase needs to either be inside the then() callback (such as console.log(this.state.url); //<<<<<<<<<<<<<SHOW URL (IT'S OK!)) or be called from there (such as this.setState({url})).