axios problem with sending all requests in react - javascript

I have an array of items in the local storage and i want to send them all at once to my API
problem is when I send them all the API tells me it got all the requests but this loop doesnt remove them from the local storage its like it didn't get a response or something
let local_items = localStorage.getItem("items")
local_items = JSON.parse(local_items)
loadingToast("Syncing items")
for (let i = 0; i < local_items.length; i++) {
axios.post('/items', {
item: local_items[i],
shop: '1',
employee: '1'
}, config).then((response) => {
if (response.status === 200) {
local_items.splice(i, 1)
//it counts down 2 or 3 times then gets stuck on a number
alert("Item synced" + local_items.length)
localStorage.setItem("items", JSON.stringify(local_items))
} else {
dismissToast()
errorToast("Error syncing items")
localStorage.setItem("items", JSON.stringify(local_items))
return
}
}).catch((error) => {
dismissToast()
errorToast("Error syncing items")
localStorage.setItem("items", JSON.stringify(local_items))
return
})
}
}
the alert shows up for all items but the countdown gets stuck.

local_items.splice(i, 1) is not a good way to remove the elements, it will only work for the first half elements and not work for the rest.
Try local_items.shift() instead.

Related

res.send with forEach loop

I want to use a forEach loop and if the condition is true I want to send my data by res.send()
const files = readFilesSync(path.resolve(uploadFolder + `_files`));
files.forEach(el => {
if (el.name.includes(fName)) {
res.send(el.name + el.ext);
} else {
console.log('Nothing')
}
});
it works fine until I got more than one "file". If the condition is true for 2 files I got an error
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
You can't call res.send multiple times while handling the same request. One approach would be to filter the list, concatenate the relevant items and then send them all together. E.g.:
const files = readFilesSync(path.resolve(uploadFolder + `_files`));
const result =
files.filter(el => el.name.includes(fName)).map(el => el.name + el.ext).join(',');
if (result.length > 0 ) {
res.send(result);
} else {
console.log('Nothing');
}
Rather than using send() which behind the scene calls end(), consider using write as demonstrated below:
files.forEach(el => {
if (el.name.includes(fName)) {
res.write(el.name + el.ext);
} else {
console.log('Nothing')
}
});
res.end()

Why does my forEach() loop only execute once?

I seem to have encountered a problem while looping through an array. The loop seems to only execute once, no matter the size of the array. I tried using different methods of looping and the error still persists.
As background information, I'm trying to make a bot with which users can award each other points. Everything else seemed alright. The only issue is that I wish to set up a maximum amount of points one user can give to another in a day, and I'm having problems looping through the array which stores this information.
These are the relevant parts of my code:
var timer = []; //Timer stores the values.
const getTimerSenderIdTable = (id) => {
let found = false;
timer.forEach(function(dat) { // This is the problematic loop.
if (dat.id === id) {
found = dat;
}
})
console.log("loop end, results: " + found);
return found;
};
const timerManager = (senderId, targetId, pointSurp) => { //All arguments are integers.
let d = new Date()
if (getTimerSenderIdTable("date") !== d.getDate()) {
timer = [];
timer.push({"id":"date", "time":d.getDate()});
if (getTimerSenderIdTable("date")) {
if (getTimerSenderIdTable(senderId)) {
console.log("path 1");
} else {
console.log("path 2");
timer.push({"id":senderId, [targetId]:pointSurp});
}
}
} else {
if (getTimerSenderIdTable("date")) {
if (getTimerSenderIdTable(senderId)) {
console.log("path 3");
} else {
console.log("path 4");
timer.push({"id":senderId, [targetId]:pointSurp});
}
}
}
console.log(timer)
};
*Edit:
Thank you for your comments. Here is an example:
Calling timerManager(123456, 654321, 3) will produce the following output:
loop end, results: false
loop end, results: [object Object]
loop end, results: false
path 2
[ { id: 'date', time: 28 }, { '654321': 3, id: 123456 } ]
(This is a repost from comments. My appologies.)
It seems because of this line
if (getTimerSenderIdTable("date") !== d.getDate()) {
timer = [];
This will empty the array and next lines of code will only push single element
as #mbojko has pointed out, you'll want to use the find method for returning the found obj inside getTimerSenderIdTable function, like this
const getTimerSenderIdTable = (id) => {
return timer.find(item => item.id === id});
};

How do I get Realtime document updates from Firebase Firestore with change.type =="added'

I presently can realtime update modified data with the following code. What I am trying to accomplish is to listen for new documents added and then realtime update my posts. I believe it is in line 8 // listen for new docs that is causing the issues.
getPosts() {
this.posts = [];
let loading = this.loadingCtrl.create({
content: "Loading Feed..."
});
loading.present();
let query = firebase.firestore().collection("posts").orderBy("created", "desc").limit(this.pageSize);
query.onSnapshot((snapshot) => {
let changedDocs = snapshot.docChanges();
changedDocs.forEach((change) => {
if (change.type == "added") {
console.log("New Message: ", change.doc.data());
for (let i = 0; i < this.posts.length; i++) {
// if (this.posts[i].id === change.doc.id) {
if (change.doc.isEqual(this.posts[i])) {
this.posts[i] = change.doc;
}
}
}
if (change.type == "modified") {
console.log("Modified Message: ", change.doc.data());
for (let i = 0; i < this.posts.length; i++) {
if (this.posts[i].id == change.doc.id) {
this.posts[i] = change.doc;
}
}
}
})
})
query.get()
.then((docs) => {
docs.forEach((doc) => {
this.posts.push(doc);
})
loading.dismiss();
this.cursor = this.posts[this.posts.length - 1];
console.log(this.posts);
}).catch((err) => {
console.log(err)
})
}
It looks to me like the problem is that you're checking to see if this.posts[i] equals the added doc, and by definition, your doc won't be included in this.posts, since it's a new document. There's nothing in the code that's updated this.posts with the new data yet.
That said, based on your code, I'm not sure I would even bother looking at docChanges. The point of using docChanges is when you want to do something very specific when a doc changes, like adding a fade-out animation when a document is removed from your data or something. Can you simply blow away your old posts array and set the new array equal to the documents you get back in your snapshot listener?

Prevent loop from stopping without having result from the query function firebase

So I query a set of nodes in firebase in order to get a value depends if the id inputted is exists, problem here is after the function returns the for loop stops looping though the return will exits a loop. So what would be the best way on querying data synchronously without stopping the loop after a return called. Hope someone helps snippet of the code attached below
loginIdentification = ['bfp','ndrmmc','pnp','rta'];
for (var counter = 0; counter < this.loginIdentification.length; counter++) { // loop the possible place of the data
console.log('loop',counter);
return this.loginFiredatabase.ref('users/' + this.loginIdentification[counter] + '/' + authData.uid).on('value', (snapshot) => { // authdata.uid is the id of the user
console.log('await');
if(snapshot.exists()) {
console.log(JSON.stringify(snapshot));
return snapshot;
}
else {
console.log('not exists');
}
});
}
I think you're trying to find the first user identification in the array that already exists in the database. If that's the case, it'd be something like this:
function findMatch(ids, callback) {
var id = ids.shift;
this.loginFiredatabase.ref('users/' + this.loginIdentification[counter] + '/' + authData.uid)
.once('value', function(snapshot) {
if (snapshot.exists()) {
callback(snapshot);
else if (ids.length > 0) {
findMatch(ids, callback);
}
else {
callback();
}
});
}
The trick about this function is that it checks one ID from the array at a time. Since data is loaded from Firebase asynchronously, it waits until it gets a result before trying the next item.
You'd call it like:
findMatch(['bfp','ndrmmc','pnp','rta'], function(result) {
if (result) {
console.log("Found match: "+result.val());
}
else {
console.log("No match found");
}
}

axios parallel requests parsing a dataTable

I've got a dataTables table with accounting data. The purpose is to send the row id to a php script which manages the accounting transfer via SAP and returns a reference number or an error text which should be inserted in the last column. This is working, but in the current version it is done by jQuery ajax in sequential, blocking order which takes it's time. My next attempt to made it quicker is done with axios and I was asking myself, if this is the correct (parallel) way? (I am new to these promises.)
for (var i = 0; i < table.rows().count(); i++) {
rowData = table.row(i).data();
axios.post('/test/data', rowData).then(function(response){
addResultToRow(response);
// promises.push(axios.post('/test/data', rowData));
});
}
function addResultToRow(response){
rowData = table.row('#'+response.data.id).data();
rowData.result = response.data.result;
table.row('#'+response.data.id).data(rowData);
table.draw();
}
I am thinking, that the request has to take place in the loop, but the ".then" call should be outside. Isn't that construct above blocking the loop until the response is received? I also tried the axios.all() way, but that is displaying all results, when the last response was received:
axios.all(promises).then(function(results) {
results.forEach(function(response) {
addResultToRow(response);
});
}).catch(function(error){
console.error(error);
});
Edit:
Maybe it is a better way to push all requests into an array:
for (var i = 0; i < table.rows().count(); i++) {
rowData = table.row(i).data();
requests.push(
axios.post('/api/test/data', rowData)
.then(function(response){
addResultToRow(response);
})
.catch((error) => {
console.error(error);
})
);
}
function addResultToRow(response){
rowData = table.row('#'+response.data.id).data();
rowData.result = response.data.result;
table.row('#'+response.data.id).data(rowData);
if (response.data.status === true) {
$(table.row('#'+response.data.id).node()).addClass('success');
updateProgressBar();
} else {
$(table.row('#'+response.data.id).node()).addClass('danger');
updateProgressBar();
}
table.draw();
}
Works well. Your thoughts?

Categories