Settimeout for each user in nodejs - javascript

I have this code that runs for each user
exports.placeStake = async(req, res) =>{
const { amount, playTime, gameStaked, stake, Id} = req.body
await Stake.create({
amount:amount,
playTime: playTime,
stake:stake,
Id:Id,
ref:crypto.randomBytes(10).toString("hex"),
status:'pending',
userId:req.user.id,
}).then(()=>{
res.status(200).send('stake placed');
}).then(()=>{
setTimeout(() => {
axios
.get(`https://v3.football.api-sports.io/fixtures?id=${Id}`, {
headers: {
'x-rapidapi-host': 'v3.football.api-sports.io',
'x-rapidapi-key': '58xxxxxxxxxxxxxxxxx'
},
})
.then((response) => {
// update the user database with response
}).catch((error) => {
console.log(error)
});
},*2 hours*);
}).catch(function (error) {
console.log(error);
if (error) {
res.status(400).send(error);
}
});
}
After 2 hours from when the game is staked I want to make an Api call in the settimeout to check the game and update the user's account
What I am confused about is if the settimeout is evaluated for each user, if not how to make is so?

First of all you assume there won't be any process interruptions for 2 hours. Like restart, crash, whatever. Extremely fragile setup.
Second if you want to run anything for each, you need a loop. I don't see any loops here.

Related

axios get request not working inside useEffect

I am using axios get request to check if user logged in or not with jwt, However, when app launched it keeps showing the loading state is it set to true in the first time the app launch then it supposes to make get request and validate the user then set loading state to false and navigate to a specific route. what i am getting is loading state is true all time and request not send to backend server.
here is the function to check if user logged in or not:
useEffect(() => {
const checkLoggedIn = async () => {
const Token = await AsyncStorage.getItem('Token');
if (Token) {
axios.get('http://localhost:3000/isUserAuth', {
headers: {
'x-access-token': Token
}
}).then((res) => {
setUser(res.data.user)
AsyncStorage.setItem("Token", res.token);
setIsLoading(false);
}).catch((error) => {
console.log(error)
setIsLoading(false);
});
} else {
setUser(null);
setIsLoading(false)
}
}
checkLoggedIn();
}, []);
and this is the backend:
app.get('/isUserAuth', verifyJWT, (req, res) => {
const token = req.headers['x-access-token'];
let sqlCheck = `SELECT * FROM users where id =?`;
CON.query(sqlCheck, req.user, (err, user) => {
if (user) {
console.log(user)
return res.status(400).json({ auth: true, user: user, Token: token })
}
})
})
Hope someone help me identifying the problem. thanks
If your loading state is not changing to false that signals to me that it's not a problem with your database call because even if your call is failing the else should trigger and still set loading to false.
Might consider narrowing down the function complexity and building up from there. Maybe something like the following to make sure your loading state is correctly updating:
useEffect(() => {
const checkLoggedIn = async () => {
setUser(null);
setIsLoading(false)
}
checkLoggedIn();
}, []);
What about setIsLoading to true when the component mounts, then run the async/await based on its value?
useEffect(() => {
setIsLoading(false);
if (!setIsLoading) {
try {
// fetch code
} catch(e) {
//some error handling
} finally {
// something to do whatever the outcome
}
}
})
// I found the solution
the problem is from the backend server where user returns undefined and the mistake i made that only check if(user) and didn't set else which not give a response back to font-end which indicate that state keep true
so backend code should be like:
CON.query(sqlCheck, req.user, (err, user) => {
if (user) {
return res.status(200).json({ auth: true, user: user, Token: token })
}else{ return res.status(400).json({ auth: false, user: null })}
})

How to globally activate useEffect in React?

I am creating a chat application in React. I am using the useEffect-hook to update the messages (all it really does is fetch them from the JSON-server). I want them to be updated every time someone in the room sends a new message.
This is one alternative I have:
useEffect(() => {
fetch('http://localhost:8000/messages/')
.then(res => {
return res.json();
})
.then(data => {
data = data.filter((msg) => msg.room === room);
setData(data);
})
.catch(err => {
console.error(`Error: ${err}`);
})
divRef.current.scrollIntoView({ behavior: 'smooth' });
}, []);
"data" is a list of messages. This shows all the messages when you enter the room, but does not load when you pass a new message. Assumingly because of the empty list at the end. Therefore I tried this:
In another component, I have a variable "sent", which is set to true every time you send a message, like this:
const onSubmit = (e) => {
e.preventDefault();
const data = {author: user, body: msg, room }
setSent(true);
fetch(`http://localhost:8000/messages/`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
})
.then(response => {
response.json();
setSent(false);
})
.catch(err => console.error(`Error: ${err}`));
setMsg('');
}
So every time you send a message, it is set to 'true', and as soon as it has been successfully sent, it is set back to 'false'. I then passed it as a prop to the component I use useEffect:
<div className='chat-main'>
<Messages user={user} room={room} sent={sent} />
</div>
Then I put the "sent"-variable in the list at the bottom of the useEffect-hook. This updates the messages for the user who sends a message, but not for the others (because, of course, "sent" only changes if you send a message)
What can I do here? Is there a way?

Is there a way to allow headers when doing a fetch request to the Stripe Billing Portal?

I have an app that allows a logged in user to upgrade their account by subscribing to a 'basic' or 'premium' subscription. Once they subscribe they can then click on a "Manage Billing" button and it will take them to a Billing Portal where they can cancel, or upgrade their subscription.
The issue that I am running into is that I am trying to make the customer be dynamic. So where it says customer: 'cus_IZvOkC9VtDRXUi', I can instead have something like customer: customer, where customer is a dynamic variable.
router.post('/customer-portal', async (req, res) => {
// const id = req.body.id
// console.log(req.body, 'ID HERE')
// User.findBy({ id })
// .then(found => {
// console.log(found, 'I FOUND YOU')
// })
// .catch(error => {
// console.log(error, 'error here on portal')
// })
// whatever customer is logged in, this needs to be the CUSTOMER line 45 - DYNAMIC
const session = await stripe.billingPortal.sessions.create({
customer: 'cus_IZvOkC9VtDRXUi',
return_url: 'http://localhost:3000/my-profile',
})
res.redirect(session.url)
const sessionURL = session.url
console.log(sessionURL,'this is session')
// console.log(session, 'this is the session')
// console.log(req,'this is req')
// res.status(302).redirect(sessionURL)
// next()
})
The problem is that when I try and send headers (so I can send the ID of the currently logged in user ID from the frontend), the req.body is an empty object and I can't see the ID. See frontend code here:
const state = useSelector(state => state)
const id = state.auth.user.id
const handlePortal = (e) => {
e.preventDefault()
console.log(id, 'JSJDHDHDHDHDHDHDH')
return fetch('http://localhost:5000/api/stripe/customer-portal', {
// mode: 'no-cors',
method: 'post',
// headers: {
// 'Content-Type': 'application/json',
// },
body: JSON.stringify({
id: id
})
})
.then((response) => {
console.log(response, 'this is the response')
const url = response.url
console.log(url, 'URURUIRIRLL')
// express cant force the front-end to redirect.
window.location = url
// return response.json()
})
.catch((error) => {
console.log(error.message, 'There was a dumb error')
})
}
The headers are commented out right now, but as soon as I add them in, I get this error:
CORS ERROR
What is super weird is this exact setup works when I create a Stripe Customer. I send the ID from the frontend at id: currentUserId. See code below:
const state = useSelector(state => state)
const currentUserId = state.auth.user.id
const handleSubmit = e => {
e.preventDefault()
return fetch(`http://localhost:5000/api/stripe/create-customer/`, {
method: 'post',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: email,
id: currentUserId
})
})
.then((response) => {
console.log(response, 'this is response handlesubmit')
return response.json()
})
.then((result) => {
setCustomer(result.customer)
console.log(result, 'THIS IS RESULT on register CUSTOMER')
})
}
Then on the backend I have my /create-customer endpoint and pull the id by req.body.id, then find the currently logged in user, then add the customer id given by stripe to the user table. This works fine without any CORS issues. See backend endpoint here:
router.post('/create-customer', async (req, res) => {
const id = req.body.id
const customer = await stripe.customers.create({
email: req.body.email,
})
res.send({ customer })
User.findBy({ id })
.then(found => {
User.updateStripeID(id, changes)
.then(changedUser => {
console.log(changedUser, 'changed!', id, changes)
})
.catch(error => {
console.log(error, 'this is stupid')
})
})
.catch(error => {
console.log(error, 'there was an error on catch', error.message)
})
})
So my question is, how do I get this working? Or how do I get my currently logged in user to the backend another way?
Couple things to note:
I do have a CORS extension that I am using in Chrome. The reason is that the my frontend will not even redirect to the Billing Portal and will throw an 'access-control-allow-origin' error. I have tried every solution on every stack overflow page about this. Literally. Spent days trying almost every solution about CORS issues. They do not work and I hope that when the app deploys live it won't have that redirect issue.
If you could not already tell my frontend is React, backend is NodeJS, and I am using Knex/SQLite3 for database tables/migrations/seeds etc.
Any help would be appreciated!

Firebase Functions: Random 404's

I'm using firebase functions on a server for API calls. Everything works fine 70% of the time, but all of a sudden some of my function calls start failing to execute, giving my API a 404, and don't work for the next few hours.
In my StackDriver I can see the function isn't called again when I try. My API just gives me a 404 without ever reaching the server.
Below is one of the calls that fails once in a while. Going to the URL i'm fetching, the GET result always shows up, so I have no clue what the issue is.
API call:
const getCreators = () => {
return window
.fetch(url + '/get-creators', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.then((res) => {
console.log(res);
if (res.status === 200) {
return res.json();
} else {
return null;
}
})
.then((data) => {
if (!data || data.error) {
return null;
} else {
return data;
}
});
};
Server code:
const app = express();
app.get('/get-creators', async (req, res) => {
console.log('creators: ');
creators
.find()
.toArray()
.then((result) => {
console.log(result);
res.status(200).send(result);
})
.catch(() => {
console.log('error');
res.send('error');
});
});
app.listen(4242, () => console.log(`Node server listening at https ${4242}!`));
exports.app = functions.https.onRequest(app);
Found it. You don't want the below code on your server:
app.listen(4242, () => console.log(`Node server listening at https ${4242}!`));
I commented this code out, republished, and all is well.
I thought having this didn't make a difference, but apparently once in a blue moon it can and will try to make the server listen locally, which gave me a 404.

Getting empty array from get

When i'm going to localhost:3000/api/categories i'm getting an empty array, but when i log my products there is alot of data inside the object. Anyone knows what i'm doing wrong? Thanks!
let products = getData()
function getData() {
return fetch('some url',
{
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}
).then(res => res.json())
};
app.get(('/api/categories'), (req, res) => {
products.then(console.log);
res.send(products);
products.then(console.log);
});
products is a promise. You can't send it to the client via res.send.
Instead, do what you're doing when you log it: use then:
app.get(('/api/categories'), (req, res) => {
products
.then(data => res.send(data))
.catch(error => {
// Send an error
});
});
Note that your code gets the products once, at startup, and then responds to the request with that static set of products.
If you want to get the products in response to the request from the client, remove the
let products = getData();
and put it in the get handler:
app.get(('/api/categories'), (req, res) => {
this.getData()
.then(data => res.send(data))
.catch(error => {
// Send an error
});
});
That repeats the request each time the client calls your server.
Of course, you might consider a middle ground, keeping and reusing the data for X seconds...

Categories

Resources