Make Jquery take a short break - javascript

Im trying to make my program just chill out for 3 sekunds and then proceed with the rest of the code - but all the stuff i can finde online just delays specifit lines of code (any way not what i was looking for)
What i wish to do is something like this
$("#one").attr("id","H1");
$("#line1").attr("id","line2");
setTimeout(3000);
$("#line2").attr("id","line1");
$("#H1").attr("id","two");
And it should just chillout for 3 sekunds where i have placed the settimeout(3000); but can make it work ? im i missing something obvious ?
Thanks alot ! :D

setTimeout() takes a function, then the delay:
setTimeout(function() {
$("#line2").attr("id","line1");
$("#H1").attr("id","two");
}, 3000);
Note that setTimeout() delays what's inside this function.
setTimeout() does not block the execution of the rest of your code,
so the following code would do exactly what console.log() says:
console.log("I log first!");
setTimeout(function() {
console.log("I log third!");
},1000);
console.log("I log second!");

Normally when someone wants JavaScript, which is a single-thread event-based model, to sleep, they do not quite understand the language.
You are not supposed to block code. Instead, you should make use of callbacks, event triggers or Promises to run dependent code when you have the dependencies.
Please read through this entire question so that you understand better what it is you are trying to do, and then decide which action to take.

Related

Detox Testing: Tracking down Javascript timers causing test framework to wait forever

The Detox test framework, according to the documentation TroubleShooting Synchronization mentions that the test framework will wait and only perform your next test statement when the app is "Idle".
The problem I have right now is that my app never goes idle because there's some timeout that's continuously firing. It could be in my code or third-party code.
Here's an example of the output:
As you can see something is creating a new timer every few milliseconds. What'd I'd like to do is track down which one, I can see the ids but don't know a good way to try and track down exactly where this (setTimeout) id is coming from.
I thought of wrapping the setTimeout function, but not sure what's the best way to proceed with that.
I could eliminate or at least wrap setTimout in my own code, that way, at least determining it's a third-party lib (which still doesn't help solve the problem).
You could track down setTimeouts easily with:
// DEV mode only!
function failOnTimeout(func) {
const setTimeout = f => {
throw new Error(`Executing timeout \n ${f.toString()} \n`);
};
// A small trick to change scope:
eval("(" + func.toString() + ")()");
}
So you can do:
failOnTimeout(someMysteriousFunction);
And will give you stack traces of the first timeout set in that function (synchronously). You can then comment that out and search for the next one.
But instead of trackig down all timeouts, a quick solution could be to just throw an uncatched error to end the process.

Can someone help me with a small JavaScript setTimeout problem?

I want to cut down the numbers of the event execution time
and so I wrote something like this:
var slow=function(method,context){
method.id&&clearTimeout(method.id)
method.id = setTimeout(function(){
method.apply(context,arguments)
}, 500)
}
window.onload=function(){
function print(){ console.log("thanks a lot") }
document.body.addEventListener("mousemove",function(){
slow(print)
}, false)
}
If I move too fast in the body, and the print function won't be executed immediately, but it doesn't seem to be work.
Can somebody help?
At first look, You have'nt provided the context parameter in the call to slow
I'd suggest using Ben Alman's throttle/debounce plugin. It doesn't actually require jQuery at all. If you don't have jQuery on the page, it just adds itself to the Cowboy namespace.
https://github.com/cowboy/jquery-throttle-debounce/blob/master/jquery.ba-throttle-debounce.js
Otherwise, you could at least get a good idea of how he does this from the code here.

Telling javascript to stop executing code and do background stuff in the middle of a function

Sorry about the title but could not come up with anything really informative and concise.
My situation is that I am launching a setTimeout and I want it to be able to run in the middle of a JS function (it is used to get around the issue with injecting GM functions into the web page).
unsafeWindow.testG = function(key, dValue){
var rValue;
setTimeout(function(){rValue = GM_getValue(key, dValue);}, 0);
alert(rValue);
alert(rValue);
return(rValue);
}
In the three tests rValue is still undefined (which makes sense because JS is single threaded for the most part).
So I have 2 solutions I have thought of.
Favourite:
Is there anyway to tell JS to sleep in the middle of a function and work on background stuff (like Timeouts)?
Other:
Does anyone know when this timeout will be called? Maybe after this function execution but before whatever called it starts up again?
In that case making rValue global would solve the issue (but make slightly messier coding).
Or will it wait until all JS is done executing?
In that case I would possibly need another setTimeout to process the result.
There is no way what you're asking for can be accompished. Until HTML5 is a wide spread standard, you can't do what you're asking without thinking asynchronously.
For example :
unsafeWindow.testG = function(key, dValue, callback){
var rValue;
setTimeout(function(){
rValue = GM_getValue(key, dValue);
callback(rValue);
}, 0);
}
and call this with a callback :
unsafewindow.testG(key, dValue, function(rValue) {
alert(rValue);
});
alert("foo");
For the last sippet, "foo" will be echoed before rValue, because testG will execute the timeout function only when the Javascript thread is available, or only when there's no other script running.
To answer your first question, there is no 'sleep' function in JS. In fact, there is a site devoted to trying to create one: http://www.devcheater.com/ The conclusion: you cannot.
If what you'd like to do is make the rest of your code run later, you can put that code in a function and setTimeout().
Of course, the usual way to handle the sort of scenario you have set up is with callbacks. Since you're basically waiting for the thing in setTimeout to happen, you can have it call the rest of your code whenever it's done. For example:
var fartResult
function waitAMinuteThenFart (callback) {
function fart () {
fartResult = 'fart'
callback(fartResult)
}
setTimeout(fart, 1000*60)
}
waitAMinuteThenFart(function (result) { alert(result) })

how to set style through javascript in IE immediately

recently I've encountered a problem with IE. I have a function
function() {
ShowProgress();
DoSomeWork();
HideProgress();
}
where ShowProgress and HideProgress just manipulate the 'display' CSS style using jQuery's css() method.
In FF everything is OK, and at the same time I change the display property to block, progress-bar appears. But not in IE. In IE the style is applied, once I leave the function. Which means it's never shown, because at the end of the function I simply hide it. (if I remove the HideProgress line, the progress-bar appears right after finishing executing the function (more precisely, immediately when the calling functions ends - and so there's nothing else going on in IE)).
Has anybody encountered this behavior? Is there a way to get IE to apply the style immediately?
I've prepared a solution but it would take me some time to implement it. My DoSomeWork() method is doing some AJAX calls, and these are right now synchronous. I assume that making them asynchronous will kind of solve the problem, but I have to redesign the code a bit, so finding a solution just for applying the style immediately would much simplier.
Thanks rezna
Synchronous requests block the entire UI, which is horrible. You are right in your assumption, but if you want to continue down this path to the inner circles of $hell, try this:
function () {
ShowProgress();
window.setTimeout(function () {
DoSomeWork();
HideProgress();
}, 0);
}
Note that I have not tested this. Try playing with the time-out value (currently 0) if you still do not see anything.
Try throwing the HideProgress method into a setTimeout. For example:
function() {
ShowProgress();
DoSomeWork();
setTimeout(HideProgress,0);
}
Even though the delay is supposedly 0 milliseconds, this will have the net effect of throwing the HideProcess method to the end of the queue and may give the browser the breathing room it needs.
[Edit] I should have mentioned that this method does have a drawback if you invoke this method very often and rapidly: a race condition. You could end up with a previous timeout executing while another DoSomeWork() is executing. This will happen if DoSomeWork take a very long time to finish. If this is a risk, you may want to implement a counter for your progress bar and only execute HideProgress if the counter that started it is the same as the counter's present value.

How can I tell when changes to jquery html() have finished?

I'm using jQuery to change the HTML of a tag, and the new HTML can be a very long string.
$("#divToChange").html(newHTML);
I then want to select elements created in the new HTML, but if I put the code immediately following the above line it seems to create a race condition with a long string where the changes that html() is making may not necessarily be finished rendering. In that case, trying to select the new elements won't always work.
What I want to know is, is there an event fired or some other way of being notified when changes to html() have finished rendering ? I came across the jQuery watch plugin, which works alright as workaround but it's not ideal. Is there a better way ?
As a commenter already mentioned, JavaScript is single threaded, so you can't get race conditions.
What may trip you up however, is the fact that the UI will not update itself based on JavaScript, until a thread is finished. This means that the entire method must finish, including all code after you call html(...), before the browser will render the content.
If your code after calling html(...) relies on the layout of the page being recalculated before continuing, you can do something like this:
$("#divToChange").html(newHTML);
setTimeout(function() {
// Insert code to be executed AFTER
// the page renders the markup
// added using html(...) here
}, 1);
Using setTimeout(...) with a time of 1 in JavaScript defers execution until after the current JavaScript code in the calling function finishes and the browser has updated the UI. This may solve your problem, though it is difficult to tell unless you can provide a reproducible example of the error you're getting.
use .ready jQuery function
$("#divToChange").html(newHTML).ready(function () {
// run when page is rendered
});
It's 7 years latter and I just ran into a scenario exactly like the one #mikel described, where I couldn't avoid a "timer based solution". So, I'm just sharing the solution I developed, in case anyone out there is still having issues with this.
I hate having setTimeouts and setIntervals in my code. So, I created a small plugin that you can put where you think it's best. I used setInterval, but you can change it to setTimeout or another solution you have in mind. The idea is simply to create a promise and keep checking for the element. We resolve the promise once it is ready.
// jquery.ensure.js
$.ensure = function (selector) {
var promise = $.Deferred();
var interval = setInterval(function () {
if ($(selector)[0]) {
clearInterval(interval);
promise.resolve();
}
}, 1);
return promise;
};
// my-app.js
function runWhenMyElementExists () {
// run the code that depends on #my-element
}
$.ensure('#my-element')
.then(runWhenMyElementExists);

Categories