Fetching api response slow and not be stable - javascript

I need to get the value (totaluser) as soon as possible , but when the server change the data (totaluser) , the reponse is not stable about the time returning , sometimes get the reponse for 30ms and sometimes get for 5000ms , can someone give any solution to get this more stable and get better about the performance ? , i just want to get the value as soon as possible when the server update it?
var refreshIntervalId = setInterval(function () {
fetch('**the link for api **')
.then(res => res.json()).then((out) => {
var variable = out.totalUser[0].count;
if( variable > 20 ){
// do something ...
}
})
}, 10);

Related

Sending a message in smaller chunks

I am using DiscordJS and their API has a character limit and will reject message if limit is exceeded.
Through fetchData()I am successfully building assignedPrint, which is an array of messages that I would like to send over the API.
So I already have the array ready to go but I am also using an auto update feature (courtesy of WOK) where every set amount of time, array would be flushed refilled with fresh data and sent over again for editing the original message through the message.edit() method.
It works just fine but I am forseeing that my array might get bigger over time and sending a single message may break things because of the API max character limit.
const getText = () => {
return assignedPrint
+ greengo + 'Updating in ' + counter + 's...' + greenstop;
};
const updateCounter = async (message) => {
message.edit(getText());
counter -= seconds;
if (counter <= 0) {
counter = startingCounter;
// emptying the array before fetching again for the message edit
assignedPrint = [];
await fetchData();
}
setTimeout(() => {
updateCounter(message);
}, 1000 * seconds);
};
module.exports = async (bot) => {
await fetchData();
const message = await bot.channels.cache.get(tgt).send(getText());
updateCounter(message);
};
As you can see, the hurdle is that getText()includes everything.
I tried sending one element as a time using for (cont e of assignedPrint) and it worked but how can I edit every message upon refreshing data, knowing that new data may be added or some already sent data could be removed...
The easiest of course is to do it in one single message but again, it may hit the quota and cause a crash.
Thanks.

Limit messages to every 500 ms

I have some websocket that sends around 100's of data per second,I want to limit it to only 1 data per 500 ms.
onMessage(data) {
console.log(data); // This prints around 100 different times within 1 second
}
I tried something like below , Is this the right approach or is there any other better way to do it ? because this code runs 100 times per second.
var lastlog = new Date().getTime();
onMessage(data) {
currenttime = new Date().getTime();
if ( currenttime - lastlog > 500) {
console.log(data);
lastlog = new Date().getTime();
}
}
P.s : I can ignore remaining data and will be able to reduce the 500 ms to 200ms.. that is 5 data per second.
Here is another way of doing it, using the npm package throttle-debounce. This method is not "better". It can result is less code typed but you might not want the dependency on the package.
You can use the throttle function and specify how many milliseconds until it can be called again. Setting the second argument to true prevents the last request from being deffered -https://www.npmjs.com/package/throttle-debounce#notrailing.
The example below uses the library to throttle how often a button is pressed.
const { throttle } = throttleDebounce
const handleRequest = throttle(500, true, () => {
console.log('this request will be handled')
})
<script src='https://cdn.jsdelivr.net/npm/throttle-debounce#3.0.1/umd/index.js'></script>
<button onClick="handleRequest()">Mimick sending message</button>
Your use case might look like this:
import { throttle } from 'throttle-debounce'
const onMessage = throttle(500, true, () => {
console.log(data);
})
Less lines than your example, but that doesn't mean it's "better".

How to handle localstorage in asynchronous way?

In my typescript application, i am having two files say,
File 1 and File 2,
Whereas in File 1, i would like to store a value in localstorage like,
private load() {
return this.entityService
.load(this.$scope.projectRevisionUid)
.then(resp => {
localStorage.removeItem('employeerates');
this.$scope.employeeRates = resp.employeeRates;
return this.refreshCostRate(...resp.employeeRates)
.then(() =>
localStorage.setItem(
'employeerates',
JSON.stringify(this.$scope.employeeRates)
)
)
.then(() => this.refreshBillRate(...resp.employeeRates))
.then(() => resp.employeeRates.forEach(erm => this.calculate(erm)))
.then(() => DatepickerUtil.reinitializeDatepickers(this.$scope));
})
}
In File 2, i am having the following,
const employeerates = JSON.parse(
localStorage.getItem('employeerates')
);
if (employeerates && employeerates.length != null) {
employeerates.forEach((element: any) => {
if (
this.employee.getUid() === element.user.personUid &&
element.internalRate
) {
this.cost_rate_uom = element.internalRate * this.uom_factor;
this.cost_rate_per_hour =
this.cost_rate_uom / this.uom_factor;
this.cost_rate.setValue(this.ap4_cost_rate_per_hour);
}
});
}
Here setting localstorage in File 1 is asynchronous, i am unable to fetch the data at right time in File 2..
Kindly help me to achieve the result of getting localstorage in file 2 without using setTimeOut (because it doesnot solve my issue as i have already checked).
Please help me to pass localstorage value from one file to another which is async..
Update:
I couldn't get any other method of passing the data this.$scope.employeeRates from file 1 to file 2, for which i have used this localstorage method.. So after the async function this.refreshCostRate(...resp.employeeRates) i need to call the localstorage but before that itself my file 2 runs, but above the line this.refreshCostRate(...resp.employeeRates), if i set the localstorage then i am getting localstorage in file 2, but the case is after refresh function only i will get the exact value..
If you suggest any other way of passing data from one ts file to another ts file, then it would also be helpful.. Thing is after this.refreshCostRate(...resp.employeeRates) i will get the exact value for this.$scope.employeeRates which i need to send to file 2..
Yes we can achieve using storage change event listener
window.addEventListener("storage", ()=>{alert("D")});
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/onChanged
First, I'm not sure what framework you're using, though since I really don't know any frameworks that wouldn't help me anyway. What I think might work is for the "file 1" code to expose the Promise object created each time that rate table needs to be updated. It's generally considered "bad" to have global variables, and indeed it only has to be globally reachable. As long as code running anywhere in the page can find it, that's good enough; for the example I'll use a global.
So in "file 1" you have:
localStorage.removeItem('employeerates');
this.$scope.employeeRates = resp.employeeRates;
return this.refreshCostRate(...resp.employeeRates)
.then(() =>
localStorage.setItem(
'employeerates',
JSON.stringify(this.$scope.employeeRates)
)
)
That code clears the rate table storage and starts the process to get new rates. What I suggest is to store the Promise in the global:
localStorage.removeItem('employeerates');
this.$scope.employeeRates = resp.employeeRates;
window.employeeRatesPromise = this.refreshCostRate(...resp.employeeRates)
.then(() =>
localStorage.setItem(
'employeerates',
JSON.stringify(this.$scope.employeeRates)
)
);
return window.employeeRatesPromise;
Now, in "file2", you can do everything as a .then() callback:
if (window.employeeRatesPromise) {
window.employeeRatesPromise.then(() => {
const employeerates = JSON.parse(
localStorage.getItem('employeerates')
);
if (employeerates && employeerates.length != null) {
employeerates.forEach((element: any) => {
if (
this.employee.getUid() === element.user.personUid &&
element.internalRate
) {
this.cost_rate_uom = element.internalRate * this.uom_factor;
this.cost_rate_per_hour =
this.cost_rate_uom / this.uom_factor;
this.cost_rate.setValue(this.ap4_cost_rate_per_hour);
}
});
}
else {
// whatever makes sense when there's no data at all
}
If the rate table update has completed, then the global Promise will be resolved and the function passed to .then() runs basically immediately. That can happen more than once on the same Promise object. However, when the "file 1" update process is still pending, the "file 2" code will wait for the local storage to be updated.
}
}

Web BLE Characteristic startNotifications sometimes doesn't bind

I'm using web BLE. I have based my code according to the example of the heart rate measurement.
Everything is working fine most of the time. But sometimes, even if the connection is successfully made, when I try to bind to the notification, it doesn't work.
The link is made in this function :
_startNotifications(characteristicUuid) {
let characteristic = this._characteristics.get(characteristicUuid);
console.log(characteristic);
return characteristic.startNotifications().then(() => characteristic);
}
When everything is OK, I can see in the console that BluetoothRemoteGATTCharacteristic has a value : DataView(2) {}
Otherwise, when it's not working it has a value : null
I would like to be able to retry automatically, if I detect that the value is null. But I'm not familiar with Promise (I think this is it) and console.log(characteristic.value) doesn't work here.
How would you approach this ?
What I ended up doing is "bypass" the issue. So it's a more algorithmic resolution than a pure Javascript one.
I didn't change the connection function, so it is still called like this :
device._startNotifications(some_uuid).then(handleHeartRateMeasurement)
I check everything in the handleHeartRateMeasurement function :
var ready = false;
function handleHeartRateMeasurement(heartRateMeasurement) {
console.log("Hold on...");
heartRateMeasurement.addEventListener("characteristicvaluechanged", event => {
// Everytime the value change, this should be triggered
// If it did not, variable "ready" will stay false
ready = true;
var value = device.parseValue(event.target.value);
// Do something with value here
});
var check = function(){
// If we have received data from characteristic, we are ready to go !
if(ready === false){
console.log("Device connected but not receiving data");
// Stop the current notification subscription
device.stopNotificationsHeartRateMeasurement();
// Start a new one
device._startNotifications(some_uuid).then(handleHeartRateMeasurement);
setTimeout(check, 1000); // check again in a 1s
}
else{
console.log("Device connected and receiving data");
}
}
setTimeout(() => {
check();
}, 500);
}

Pass variable through asynchronous function

First of all, I'm using JQuery. Take a look:
$(document).ready(function() {
var btcusd = 600;
function getRate() {
$.get("rate.php", function(data) {
var btcArr = JSON.parse(data, true);
btcusd = btcArr["last"];
//This will give me the correct value
console.log(btcusd);
});
}
setInterval(function() {
//This will say 600 every time
console.log(btcusd);
//Update rate for next loop
getRate();
}, 3000);
});
Chrome console gives me the 600 every 3 seconds. If I do this manually in the chrome live console, I will get a real value, like 595.32.
Why does this not work like intended?
Thanks for help.
I think #Tobbe is quite on point here. One thing you can do to confirm, is to add something like console.log( btcArr ) and that should show you whether you're getting anything back.
I set up a not too different demo that should that once the ajax callback successfully updates the value, it never goes back to 600, showing that indeed the value does get changed in the callback and the new value is available outside the ajax callback.
The ajax code I used is:
function getRate() {
var gafa = "https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=100&q=";
var url = gafa + encodeURI('http://news.yahoo.com/rss/sports/')+"&callback=?";
$.getJSON(url, function(data) {
//var btcArr = JSON.parse(data, true);
var xData = data.responseData.feed.entries
//btcusd = btcArr["last"];
btcusd = xData.length;;
//This will give me the correct value
console.log(btcusd);
});
}
The rest of the code is yours: WORKING JSFIDDLE DEMO

Categories