Use SetTimeOut, so messages are not sent too rapidly after one another - javascript

I'm making a small chat :)
When a user is typing (or stopped typing), this is being signalled to other users, and only when user switches between typing or not (checking if the textarea is empty or not)
Now I want to prevent those signals from being sent too rapidly after one another.. I'm thinking that some settimeout could do it, but I don't know how or where to put it in my code:
var istyping = false;
var wastyping = false;
chatfield.keyup(function(e) {
if (e.keyCode != 13) {
function typesignal(state) {
channel.send(JSON.stringify({
username: username,
type: 'typing',
message: state
}));
}
if (chatfield.val()) {
istyping = true;
if (wastyping==false) {
typesignal(1);
wastyping = true;
}
} else {
istyping = false;
if (wastyping==true) {
typesignal(0);
wastyping = false;
}
}
}
});

You might call this 'throttling' and I've used it a bunch on things like autocomplete dropdowns so you don't kill the server on every keystroke. The JS standard library lets you clear timeouts, and also returns an id when setTimeout is called. So you can use this id to clear the timeout (prevent the callback from being called within the time period) if the function is called again within a certain period of time. So for example:
var timeId;
function throttle(callback, ms) {
if (timeId) {
clearTimeout(timeId);
}
timeId = setTimeout(callback, ms)
}
chatfield.keyup(function(e) {
throttle(your_fn, 500);
});
In case it's not clear, the setTimeout executes a function after a certain period of time, specified in milliseconds as the second parameter. So, if I call setTimeout(function(){},300) that function will be called after 300 ms. And I can also say, "cancel" that original request. So if I get another request before the first one has fired, just cancel it and start over. That's the pattern I was trying to describe above :-)

I'd do this
chatfield.keyup(function(e) {
if (e.keyCode != 13) {
function typesignal(state) {
channel.send(JSON.stringify({
username: username,
type: 'typing',
message: state
}));
}
if (chatfield.val()) {
istyping = true;
if (wastyping==false) {
typesignal(1);
wastyping = true;
}
} else {
istyping = false;
if (wastyping==true) {
typesignal(0);
wastyping = false;
}
}
}
function doNothing() {
}
setTimeout("doNothing()",1000);
});

Related

my functions are mixed and the engine executing what ever he wants

so i was told to Present a loader to the user when a call is made to the server (indicating the server is calculating) Present an error to the user if the input number is more than 50, and do not send a server request Try passing the number 42 to the server. The server will send back an error, present this error to the user.
now what i did is everything besides the last error to present it to the user.
i have tried everything i could think of, and no matter what the user types, it displays both of the messages.
this is my code:
const clcBtn = document.getElementById("calcButton");
let clcInput = document.getElementById("calcInput");
const result = document.getElementById('paragraph');
const loader = document.getElementById('spinner');
const error = document.getElementById('error-message');
const serverError = document.getElementById('server-error');
clcBtn.addEventListener("click", calcFunc);
function numValidate(value) {
if(value > 50) {
return false;
}
return true;
}
function calcFunc() {
if (!numValidate (clcInput.value)) {
error.style.display = "block"
setTimeout(() => {
error.style.display = "none";
}, 5000);
console.error("Can't be larger than 50") // only bec it's a cool feature :D
return;
}
loader.classList.add("spinner-border");
fetch(`http://localhost:5050/fibonacci/${clcInput.value}`).then(function (response) {
return response.json().then(function (data) {
result.innerHTML = data.result;
});
});
setTimeout(() => {
loader.classList.remove("spinner-border");
}, 1000);
}
this is my code with what i have tried to add (on of the things i have tried.. this is the best output i could come with)
code:
// additional code to present to the user the error message if the input value is equal to 42.
clcBtn.addEventListener("click", errMsg);
function numValidateTwo(value) {
if(value === 42) {
return true;
}
return false;
}
function errMsg() {
if (!numValidateTwo (clcInput.value)) {
serverError.style.display = "block";
}
return;
}
a little bit more about what i am trying to achieve:
i want to present this error message to the user, whenever the input value is equal to 42.
is it related to async or callback? which i need to go through the lectures again.. but right now i need to solve this bec i have no time.
what did i do wrong ?
and how i can make it work?
can someone explain this to me?
thanks in advance!

Javascript setInterval not working?

I am working on a bit of code in Javascript that polls a time consuming process that is running in a webservice and returns the status every two seconds. The processPoll function is never getting hit and I can not figure out why the setInterval does not work. I think I have the scope right so I'm not sure why processPoll does not start.
var processId;
var timerId;
function processStartReturn(retVal) {
if ((retVal != null) && (retVal != "")) {
processId = retVal;
timerId = setInterval(processPoll, 2000);
alert(processId); --> alerts correct Id
}
}
function processPoll() {
alert("This alert never shows up!");
WebService.MyFunction(processId, 0);
}
function startPoll() {
var appName = document.getElementById("appName").value;
var threadId = appName + "object";
processStartReturn(threadId);
}
Edit: I have added the startPoll() function that is started with an onclientclick event.

Strange setTimeout clearing behaviour with jQuery AJAX

So, I'm trying to set a timeout on each request that is sent and work out if one is taking "too long". I'm watching the network tab and each request is well under 300ms, however 'too long' gets logged 6 times! (the number of requests I'm sending). Is there something I'm doing wrong with variables, setTimeouts or something?
var ajaxMonitor = {};
function timingStart() {
var url = arguments[2].url;
ajaxMonitor[url] = {};
ajaxMonitor[url].timer = setTimeout(function () {
console.log('too long');
}, 300);
}
function timingEnd() {
var url = arguments[2].url;
clearTimeout(ajaxMonitor[url].timer);
}
$(document).ajaxSend(timingStart);
$(document).ajaxComplete(timingEnd);
As pointed out in the comment it might be because you are calling the same url multiple times. If that is the case, one way to fix that problem is to clear the interval before setting it:
function timingStart() {
var url = arguments[2].url;
clear(url);
ajaxMonitor[url] = {};
ajaxMonitor[url].timer = setTimeout(function () {
console.log('too long');
}, 300);
}
function timingEnd() {
var url = arguments[2].url;
clear(url);
}
function clear(url) {
if(ajaxMonitor[url])
clearTimeout(ajaxMonitor[url].timer);
}
$(document).ajaxSend(timingStart);
$(document).ajaxComplete(timingEnd);

How to ensure that function a has been run before function b..?

I'm having some trouble with the following javascript code..
var returnValue = false;
function hasItem(id) {
//I want this entire function to run first
db.transaction(function(tx) {
tx.executeSql("SELECT * FROM library WHERE id == "+id,[],function(tx, results) {
returnvalue = results.rows.length>0;
},errorCB);
},errorCB,successCB);
//then this
return returnvalue;
}
But the sql-function appears to run in a separate thread, making the function return false all the time.. is there any way "to force a wait"..?
is there any way "to force a wait"..?
No. What you must do is change your hasItem function so that it accepts a callback that provides the information, instead of returning a value.
It's a bit tricky not knowing what your errorCB and successCB callbacks do, but something along these lines:
function hasItem(id, callback) {
var returnValue = false;
db.transaction(function(tx) {
tx.executeSql("SELECT * FROM library WHERE id == "+id,[],function(tx, results) {
returnValue = results.rows.length > 0;
},failed);
},failed,function() {
successCB();
callback(returnValue);
});
function failed() {
errorCB();
callback(null); // Or whatever you want to use to send back the failure
}
}
Then, instead of this
if (hasItem("foo")) {
// Do something knowing it has the item
}
else {
// Do something knowing it doesn't have the item
}
You use it like this:
hasItem("foo", function(flag) {
if (flag) {
// Do something knowing it has the item
}
else {
// Do something knowing it doesn't have the item
// (or the call failed)
}
});
If you want to tell, in the callback, whether the call failed:
hasItem("foo", function(flag) {
if (flag === null) {
// The call failed
}
else if (flag) {
// Do something knowing it has the item
}
else {
// Do something knowing it doesn't have the item
}
});

memory leak in ajax - setInterval

I have an ajax code which causes memory leak (especially in IE).
function setStatus() {
var formInput=$(this).serialize();
$.getJSON('CheckStatus.action', formInput, function(data) {
if(data == false) {
function getEventsPeriodicaly() {
getEvents();
};
var timer = setInterval(function () {getEventsPeriodicaly();}, 5000);
}
}
);
}
function getEvents() {
var formInput=$(this).serialize();
$.getJSON('StartEP.action', formInput,function(data) {
var txt = $("#txtEventsArea");
if(data != null && data.toString().length!=0) {
txt.val(data.join('\n') + '\n' + txt.val());
data=null;
}
}
)}
StartEP
public String startEP() throws Exception {
logger.info("[EP] In startEP");
try {
synchronized(status) {
if(!getStatus()) {
EventProcessor amiep = EventProcessor.getInstance();
amiep.addObserver(this);
new Thread(amiep).start();
setStatus(true);
}
}
} catch (Exception ex) {
logger.error("Unable to start EP", ex);
return ERROR;
}
logger.info("[EP] In startEP, before loop");
while(!gotNewData) {
Thread.sleep(4000);
}
gotNewData = false;
logger.info("[EP] Out startEP");
return SUCCESS;
}
The StartEP action returns messages (about 5KB on each request). First I thought it concerned with setting text to textarea, but after some tests got that it is not the reason. Could it be setInterval method?
Is there any considerations?
thanks
I would say this looks pretty suspect:
while(!gotNewData) {
Thread.sleep(4000);
}
Where is gotNewData set? If you call the web service once and set gotNewData to true and then call another web service and set gotNewData to false I don't think there is a guarantee that you're setting the variable within the same instance of the application. Therefore, if you are not, then every time you're hitting the web service you are starting a new thread and then continually putting it back to sleep.

Categories