Prevent fetch request if browser session variable exists - javascript

I have a function that pulls the users location based on an API request and stores it as a session variable in the browser. Then, it gets the phone number based on the users location which is stored in the session variable. However, I'm trying to prevent the fetch requests from being made if the browser has the session variable stored, to prevent unnecessary API requests.
I'd tried checking if the country_code variable exists in the session storage, but that seems to lock up the subsequent requests:
async function fetchCountryAndPhone() {
if (!sessionStorage.getItem("country_code")) {
const [countryCode, phoneNum] = await Promise.all([
fetch('/userinfo/'),
fetch('/contacts/')
]);
const country = await countryCode.json();
sessionStorage.setItem("country_code", country.country_code.toLowerCase())
}
const phone = await phoneNum.json();
return [phone];
}
fetchCountryAndPhone().then(([phone]) => {
let getCountryCode = sessionStorage.getItem("country_code");
let getContactNum = phone[`${getCountryCode}`].sales
....
}).catch(error => console.warn(error));
How can I adjust the logic to prevent subsequent fetch requests if the country_code session variable exists, and just use the one that's already been stored?

Save both country_code and phone in session storage.
async function fetchCountryAndPhone() {
if (!sessionStorage.getItem("country_code")) {
const [countryCode, phoneNum] = await Promise.all([
fetch('/userinfo/'),
fetch('/contacts/')
]);
const country = await countryCode.json();
sessionStorage.setItem("country_code", country.country_code.toLowerCase());
const phone = await phoneNum.json();
sessionStorage.setItem("phone", JSON.stringify(phone));
}
let phone = JSON.parse(sessionStorage.getItem("phone"));
return [phone];
}

Related

I want to receive data from external Api in my server ( Node Js Express) and send it to my front end

I have being stuck with this code more than 1 week. I still cannot make it work as it should.
I want to receive data from an external Api, but I have two issues that I am not sure how to handle:
1- The URl of my api call is from different users so I need to change the url base on the user's ID and make an API call per user.
I want to send the data received from the external API to an array and if the user's ID is inside the data I just want to update the data, if it is not in the array just insert the data.
2- This process of calling the api needs to be repeat every 20 seconds to receive the update information.
Here is the code I am trying to fix:
This is the code in my backend/server.I am using Node JS Express.
let userData = [];
async function callApi() {
for( let i = 80; i < 82; i++ ){
const url = "https://myurl.com/user/" + i;
//Making the APi call
const response = await fetch(url);
const information = await response.json();
let check = userData.find(obj => obj.data.userId === information.data.userId);
if (check == undefined) {
userData.push(information);
} else{
const index = userData.findIndex( x => x.data.userid === information.data.userId);
userData[index] = information;
}
}
callApi();
//Repeat the api call every 20 seconds
setInterval(function(){
callApi();
}, 20000);
// free endpoint
app.get("/free-endpoint", (req, res) => {
res.json(userData);
});
**In my frontend: **
I want to make a https request to my server url/free-endpoint and get the updated data from userData every 20 seconds.
I hope you can help me!
Thank you
I have try setInterval inside my route
app.get("/free-endpoint", (req, res) => {
res.json(userData);
});
but it always appear an error that I cannot send the header more than one time

Retrieving values from browser cache

I've created a service worker that performs a fetch and then immediately stores the data in the cache.
self.addEventListener('install', async function(e) {
try {
const fileCache = await caches.open(CACHE_NAME);
await fileCache.addAll(FILES_TO_CACHE);
const dataCache = await caches.open(DATA_CACHE_NAME);
const dataFetchResponse = await fetch('/api/transaction');
return await dataCache.put('/api/transaction', dataFetchResponse);
} catch (error) {
console.log(error);
}
});
After performing this I'm trying to make it so that I can test how long it's been since the last data fetch in order to determine if the data needs to be updated. My Transaction model adds a timestamp onto the data so I'd ideally want to test the timestamp of the last transaction against the current time but I'm not sure how to do it.
I've attempted to do cache.match() but it doesn't return the entire object of the matched key. I know localStorage has a .getItem() method but I don't see any methods for cache that are similar.
Any ideas on this one?
Figured out how to get the information. You have to .match() the key of the data stored in the cache and since it returns a promise you convert that into a .json() object.
async function getCachedData(cacheName, url) {
const cacheStorage = await caches.open(cacheName);
const cachedResponse = await cacheStorage.match(url); // Returns a promise w/ matched cache
if(!cachedResponse || !cachedResponse.ok) {return false}
console.log(await cachedResponse);
console.log(await cachedResponse.json()); // prints json object with value of key matched
return await cachedResponse.json();
};

Async Await not awaiting for async method to occur

I am building up a shopping website for a project. I currently am writing a loadcart method using javascript. Basically what happens is that I store my cart data in my session storage. If no shopping cart data is found in session storage I fetch from the database. I made the function an async function because my getshoppingcartDB function is an asynchronous method.
When there is no data in session storage, I expected my method to enter the if clause, fetch the data from the database and update the cart array. However, my cart array is still blank. I notice that the cart array is ONLY updated later as shown by the screenshot.
As such, Im a litte curious how the await function? I thought the await is supposed to wait for a response back first but it seems here that it is being executed asynchronously.
This is my load cart function
// Load cart
cart = [];
async function loadCart() {
console.log("LOAD CART")
var uname = document.getElementById("username").innerText
uname = uname.trim();
if (sessionStorage.getItem("shoppingCart") === null) {
console.log("check null")
const cartdata= await getshoppingcartDB(uname);
cart = cartdata
}else{
cart = JSON.parse(sessionStorage.getItem('shoppingCart'));
}
return cart
}
loadCart().then(function(response){
cart = response
})
This is my async function for retrieving data from the database
async function getshoppingcartDB(email) {
let params = {
"email": email
};
let query = Object.keys(params)
.map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))
.join('&');
let url = '/getcartdatabyemail?' + query;
const response = await fetch(url);
return response.json()
}
PS: I edited my function as per Mike's advice but stll doesnt seem to work? I also cant seem to do a result = await loadCart().

Set all instances of a value to null in Realtime Database: Firebase Cloud Functions

I want to take wipe all of the values of a particular userID connected to many different post keys in my database by turning the userID to null. The userIDs are attached to post keys in the path: posts/ivies/userIDs in my database. Here is how the database looks:
So I decided to run the following for loop to filter for the userID and turn it to null:
exports.wipeData = functions.https.onRequest(async (req, res) => {
const original = 'ppPXA8MvaSRVbmksof0ByOzTxJ92';
const snapshot = await admin.database().ref('/posts/ivies/userIDs/');
console.log((snapshot));
for (let value in snapshot.val) {
if (value == original) {
snapshot.val.set("null")
}
else {
console.log(value)
}
}
res.redirect(303, snapshot.ref.toString());
// [END adminSdkPush]
});
Although this function deploys and runs, it does not turn 'ppPXA8MvaSRVbmksof0ByOzTxJ92' to 'null' as anticipated. Thank you for your help.
Your general approach seems fine, but you have a few bugs in there.
This should work better:
exports.wipeData = functions.https.onRequest(async (req, res) => {
const original = 'ppPXA8MvaSRVbmksof0ByOzTxJ92';
const ref = admin.database().ref('/posts/ivies/userIDs/');
const query = ref.orderByValue().equalTo(original);
const results = await query.once('value');
const updates = {};
results.forEach((snapshot) => {
updates[snapshot.key] = null;
});
await ref.update(updates);
res.status(200).send(JSON.stringify(updates));
})
The main changes:
Your snapshot variable doesn't contain any data yet, as you're not reading from the database. The once('value') in my code performs that read.
This code uses a query to select only the nodes that have the right value. When your number of users grows, this significantly reduces the database load (and cost).
This code first gathers all updates into a single object, and then sends them to the database as one call.
The await in await ref.update(updates) is probably the main fix, as it ensures the redirect is only executed once the database writes has been completed.
I am not familiar with firebase cloud functions, but in regular client-side firebase code val needs to be called as a function, and you have to wait for the value from a reference. You could try:
exports.wipeData = functions.https.onRequest(async (req, res) => {
const original = 'ppPXA8MvaSRVbmksof0ByOzTxJ92';
const userIDs = await admin.database().ref('/posts/ivies/userIDs/');
userIDs.once("value", snapshot => {
var lookup = snapshot.val();
for (let key in lookup) {
var value = lookup[key];
if (key == value) {
userIDs.child(key).set(null);
}
}
res.redirect(303, userIDs.ref.toString());
});
});

AdonisJS Associate with multiple oneToMany relationships

How do I associate an array of values from a oneToMany relationship in Adonis.
The docs show the following to associate a single value
const Profile = use('App/Models/Profile')
const User = use('App/Models/User')
const user = await User.find(1)
const profile = await Profile.find(1)
await profile.user().associate(user)
What if my form had submitted an array of multiple user id's
I know I could use array.map and loop over each one, but that is an asynchronous command and my controller would try to respond to the client before map had completed.
users.map(async (u)=>{
let user = await User.find(u)
await profile.user().associate(user)
})
return //I think this would return before the above map function completed.
You can do it with a for of
for (const u of users) {
const user = await User.find(u)
await profile.user().associate(user)
}

Categories

Resources