I am making 2 requests using for loop simultaneously when someone clicks on a button. Then I post a message to their profile; say the messages are the following :
var my_array=["Hi i am jason", "I am feeling great today"];
Above is the array and then I update the statuses using the for loop, so first it loops through the first message and then through the second message.
As I am making this request, those 2 messages are updated on their profile at the same time(maybe a delay of some ms). What I want is the delay of 2s between those 2 messages(indirectly I want the delay between the for loop indices).
So when I click on the button the first message should be updated right away and the second one after 2s.
How can I achieve this?
You can create a delay in JavaScript with setTimeout: https://developer.mozilla.org/de/docs/Web/API/WindowTimers/setTimeout
For example:
window.setTimeout(function() {
//do your second API call
}, 2000); //2 seconds delay
One way to solve this (untested, but you should get the idea):
var currentMessageId = 0;
function doAPICall() {
//do API call with my_array[currentMessageId]
currentMessageId++;
if (currentMessageId < my_array.length) {
window.setTimeout(doAPICall, 2000); //2 seconds delay
} else {
//done
}
}
You can also encapsulate the whole code in a function, so you can call it on button click. Or just set the currentMessageId parameter to zero in the else block.
Btw, prefilling the message is not allowed according to the platform policy. The user must write every single message by himself.
Related
I have this situation, i'm building a shopping cart, and i need to make a http request each time a product is added or its quantity is changed.
I have one button to add 1 unit of a product to the cart, it supposed that each unit added should make the http request, but i want to avoid to make to many calls at once... So i wanted to set a timeout for the request, but if within 3 secs the user clicks again, then i should cancel the last request with old data and then set a new timeout fot the request with the new data.
So i came up with this solution
function doRequest(){
clearTimeout(state.request);
state.request = setTimeout(updateCartService, 180);
}
The function is inside another function that retrieves the state object (A collection of variables and data persistent through all the application). The updateCarteService function contains the http request.
However all the requests are still being made, if i click 5 times the button that triggers doRequest, the call i being excecuted 5 times.
Have any idea of what could be wrong or pherhaps a better aproach to achieve my goal?
If it helps i'm bulding the site using vueJs, vuex (flux) and this code is inside an action.
setTimeout takes milliseconds, so you set timout for 180ms, it is too short, try 3000 for example. Here a small jsfiddle example.
https://jsfiddle.net/ShinShil/5fw2c63o/
var timeout;
$('#click').click(function() {
clearTimeout(timeout);
timeout = setTimeout(setText, 3000);
});
function setText() {
$('#text').append('text');
}
Since setTimeout crashes in while loops.
I don't know if there is a way to do it but I am trying to make one.
This is how it looks so far.
<script>
var send = true;
function sendit()
{
alert("test");
return true;
}
while(true)
{
if(send == true)
{
send = false;
setTimeout(function(){
if(sendit() == true) {
send = true;
}
}, 5000);
}
}
</script>
Is it possible this way?
You haven't explained what you want your code to do. If you want it to alert "test" every 5 seconds then you need this:
<script>
function sendit()
{
alert("test");
// Call sendit() the next time, repeating
setTimeout(sendit, 5000);
}
// Call sendit() the first time
setTimeout(sendit, 5000);
</script>
No need for a loop, just get the function to schedule itself again.
My understanding is that what you're trying to do is the equivalent of Thread.sleep(5000) in a language like Java or C#. That functionality does not exist in JavaScript. If you want to do something some amount of time after your function's execution, put it in a timeout, but one way or another, that first function will still complete in the same frame unless you're performing an enormous amount of work.
Currently, your code is setting a timeout on sendit() a practically-infinite number of times before it returns. Since JavaScript is single threaded, even if 20 seconds passed, it still wouldn't have finished your function and couldn't start looking up timeouts it needs to process. What you should be doing is something like having the inside of the timeout set another timeout, and remove the enclosing while(true). That could allow for infinite, periodic behavior as I think you're looking for.
I'm trying to implement a search bar like facebook for my website users. While you type the name, some results are displayed.
To avoid sending a request for each button pressed, i've setup a timeout. The idea is: if i'm going to type jack It doesn't make sense to search for j, ja, jac, jack, but it's better to wait for the users finishes typing before sending any request.
Once the request is sent and completes, a div called mydiv is filed with results (the request response). If after some time long enough i type another letter, another request is sent and mydiv is filled with new results.
The idea comes from this question.
Here is my simplified implementation.
var thread = null;
$('#search-user').keyup(function() {
clearTimeout(thread);
name = $('this').val(); //i get the name just typed
thread = setTimeout(function(){
get_data_with_ajax_and_put_it_in_mydiv(name);
}, 200);
});
function get_data_with_ajax_and_put_it_in_mydiv(name){
$.post()....
/*Do some stuff*/
}
As you can see, after a 200ms timeout the function get_data_with_ajax_and_put_it_in_mydiv(); is called. This function, emptys mydiv before putting new data. It works almost always, but sometimes a strange bug occurs.
I'm going to explain where i think the problem is, by providing a real example. Let us assume that get_data_with_ajax_and_put_it_in_mydiv() takes from 50ms to 1000ms to complete, depending on various factors (network speed, congestion, etc...).
At t=0 i type jac and i stop typing.
At t=200 the timeout expires and get_data_with_ajax_and_put_it_in_mydiv() runs. In this case it takes 1000ms to run
At t=210, because i'm a slow writer, i type the letter k of jack. mydiv is empty because
the first request has not yet completed.
At t=410 the timeout for the letter k epires and a second request
is sent. This time, the function takes 100ms to run.
At t=510 the second request finishes and i get the results for jack.
At t=1200 the first request finishes and i get the results for jac.
ERROR
As you can see due to impredictability of time elaped by ajax requests i got a wrong result. mydiv is filled with jac results and not jack.
SOLUTION
The first solution that came to my mind is the following: every time i call get_data_with_ajax_and_put_it_in_mydiv() i have to stop any previous request still running. How can i do that? If not possible, how can i fix this error?
Why not use a debounced function to handle the ajax call?
http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
You should use the Promise interface and use the 'done' method to chain these two operations sequentially
http://api.jquery.com/jquery.post/
I am porting an old game from C to Javascript. I have run into an issue with display code where I would like to have the main game code call display methods without having to worry about how those status messages are displayed.
In the original code, if the message is too long, the program just waits for the player to toggle through the messages with the spacebar and then continues. This doesn't work in javascript, because while I wait for an event, all of the other program code continues. I had thought to use a callback so that further code can execute when the player hits the designated key, but I can't see how that will be viable with a lot of calls to display.update(msg) scattered throughout the code.
Can I architect things differently so the event-based, asynchronous model works, or is there some other solution that would allow me to implement a more traditional event loop?
Am I making sense?
Example:
// this is what the original code does, but obviously doesn't work in Javascript
display = {
update : function(msg) {
// if msg is too long
// wait for user input
// ok, we've got input, continue
}
};
// this is more javascript-y...
display = {
update : function(msg, when_finished) {
// show part of the message
$(document).addEvent('keydown', function(e) {
// display the rest of the message
when_finished();
});
}
};
// but makes for amazingly nasty game code
do_something(param, function() {
// in case do_something calls display I have to
// provide a callback for everything afterwards
// this happens next, but what if do_the_next_thing needs to call display?
// I have to wait again
do_the_next_thing(param, function() {
// now I have to do this again, ad infinitum
}
}
The short answer is "no."
The longer answer is that, with "web workers" (part of HTML5), you may be able to do it, because it allows you to put the game logic on a separate thread, and use messaging to push keys from the user input into the game thread. However, you'd then need to use messaging the other way, too, to be able to actually display the output, which probably won't perform all that well.
Have a flag that you are waiting for user input.
var isWaiting = false;
and then check the value of that flag in do_something (obviously set it where necessary as well :) ).
if (isWaiting) return;
You might want to implement this higher up the call stack (what calls do_something()?), but this is the approach you need.
I'm creating a content rotator in jQuery. 5 items total. Item 1 fades in, pauses 10 seconds, fades out, then item 2 fades in. Repeat.
Simple enough. Using setTimeout I can call a set of functions that create a loop and will repeat the process indefinitely.
I now want to add the ability to interrupt this rotator at any time by clicking on a navigation element to jump directly to one of the content items.
I originally started going down the path of pinging a variable constantly (say every half second) that would check to see if a navigation element was clicked and, if so, abandon the loop, then restart the loop based on the item that was clicked.
The challenge I ran into was how to actually ping a variable via a timer. The solution is to dive into JavaScript closures...which are a little over my head but definitely something I need to delve into more.
However, in the process of that, I came up with an alternative option that actually seems to be better performance-wise (theoretically, at least). I have a sample running here:
http://jsbin.com/uxupi/14
(It's using console.log so have fireBug running)
Sample script:
$(document).ready(function(){
var loopCount = 0;
$('p#hello').click(function(){
loopCount++;
doThatThing(loopCount);
})
function doThatOtherThing(currentLoopCount) {
console.log('doThatOtherThing-'+currentLoopCount);
if(currentLoopCount==loopCount){
setTimeout(function(){doThatThing(currentLoopCount)},5000)
}
}
function doThatThing(currentLoopCount) {
console.log('doThatThing-'+currentLoopCount);
if(currentLoopCount==loopCount){
setTimeout(function(){doThatOtherThing(currentLoopCount)},5000);
}
}
})
The logic being that every click of the trigger element will kick off the loop passing into itself a variable equal to the current value of the global variable. That variable gets passed back and forth between the functions in the loop.
Each click of the trigger also increments the global variable so that subsequent calls of the loop have a unique local variable.
Then, within the loop, before the next step of each loop is called, it checks to see if the variable it has still matches the global variable. If not, it knows that a new loop has already been activated so it just ends the existing loop.
Thoughts on this? Valid solution? Better options? Caveats? Dangers?
UPDATE:
I'm using John's suggestion below via the clearTimeout option.
However, I can't quite get it to work. The logic is as such:
var slideNumber = 0;
var timeout = null;
function startLoop(slideNumber) {
//... code is here to do stuff here to set up the slide based on slideNumber...
slideFadeIn()
}
function continueCheck() {
if (timeout != null) {
// cancel the scheduled task.
clearTimeout(timeout);
timeout = null;
return false;
} else {
return true;
}
};
function slideFadeIn() {
if (continueCheck){
// a new loop hasn't been called yet so proceed...
$mySlide.fadeIn(fade, function() {
timeout = setTimeout(slideFadeOut,display);
});
}
};
function slideFadeOut() {
if (continueCheck){
// a new loop hasn't been called yet so proceed...
slideNumber=slideNumber+1;
$mySlide.fadeOut(fade, function() {
//... code is here to check if I'm on the last slide and reset to #1...
timeout = setTimeout(function(){startLoop(slideNumber)},100);
});
}
};
startLoop(slideNumber);
The above kicks of the looping.
I then have navigation items that, when clicked, I want the above loop to stop, then restart with a new beginning slide:
$(myNav).click(function(){
clearTimeout(timeout);
timeout = null;
startLoop(thisItem);
})
If I comment out 'startLoop...' from the click event, it, indeed, stops the initial loop. However, if I leave that last line in, it doesn't actually stop the initial loop. Why? What happens is that both loops seem to run in parallel for a period.
So, when I click my navigation, clearTimeout is called, which clears it.
What you should do is save the handle returned by setTimeout and clear it with clearTimeout to interrupt the rotator.
var timeout = null;
function doThatThing() {
/* Do that thing. */
// Schedule next call.
timeout = setTimeout(doThatOtherThing, 5000);
}
function doThatOtherThing() {
/* Do that other thing. */
// Schedule next call.
timeout = setTimeout(doThatThing, 5000);
}
function interruptThings() {
if (timeout != null) {
// Never mind, cancel the scheduled task.
clearTimeout(timeout);
timeout = null;
}
}
When a navigation element is clicked simply call interruptThings(). The nice part is that it will take effect immediately and you don't need to do any polling or anything else complicated.