I've been created a demo for RxJS scan() method but unfortunately my timer doesn't work properly and I get this error: Timer 'myTimer' does not exist
console.time('myTimer');
let source = Rx.Observable
.interval(100) // interval starts from 0
.take(4)
.scan((acc, val) => acc + val);
source.subscribe((value) => {
console.timeEnd('myTimer');
console.log('in next. Value: ', value);
});
Here is a demo in JSBin.
Here is a source that I Copy code from that.
How can fix that issue?
Once you've stopped the timer with console.timeEnd("name") it no longer exists when using chrome.
console.time("myTimer");
for(var i=0;i<10000;i++){
}
console.timeEnd("myTimer"); // works
console.timeEnd("myTimer"); // displays an error (in chrome only)
Which is pretty much what your code is doing. The first time subscribe is called your timer outputs the amount of time since it ws started. On the 3 subsequent calls it does not work.
This behaviour is specific to Chrome, it works how you expect in both IE & Firefox.
Related
I am having major issues stopping an async interval from continuing.
This starts the infinite interval:
task.interval = setIntervalAsync(
async() => await this.sendTimer(task, savedGuild), interval);
Class that creates the bug:
https://pastebin.com/qq5tReFq
Line that doesn't do anything:
while (task.interval)
clearIntervalAsync(task.interval);
Sorry if this is unhelpful, but I have tried many different types and intervals and when endTimers is called the interval continues as if nothing has happened. Please send help.
const guildTimers = timers.currentTimers.get(req.params.id);
if (!guildTimers || guildTimers?.length <= 0)
return res.json([]);
for (const timer of guildTimers)
delete timer.interval; // <- the cause of the problem
I managed to find the issue. It was found in an external file, on the API, that allows the user to view the scheduled tasks.
delete timer.interval removed the reference to the interval, and therefore stopped it from being reset as timer.interval was undefined.
I currently have a Modal popping up and want it to disappear if the user doesn't input their password for 30 seconds.
This works, but when I tried to implement it with an onChange event on the input then it stopped working. The weird part is, when I use console.log to test it, it works. Once I remove those console.log's, it doesn't work. Just curious if anyone has seen this before?
let TIMEOUT = null;
const setModalTimeout = randomFunction => {
if (TIMEOUT === null) {
// console.log('NOTE: set timeout before', TIMEOUT, new Date().toLocaleTimeString());
TIMEOUT = setTimeout(() => randomFunction(false), MODAL_TIMEOUT);
}
// console.log('NOTE: set timeout after', TIMEOUT, new Date().toLocaleTimeString());
};
const clearModalTimeout = (done) => {
if (TIMEOUT !== null) {
// console.log('NOTE: clear timeout before', TIMEOUT, new Date().toLocaleTimeString());
clearTimeout(TIMEOUT);
TIMEOUT = null;
}
// console.log('NOTE: clear timeout after', TIMEOUT, new Date().toLocaleTimeString());
done && done();
};
const resetModalTimeout = (randomFunction) => {
// console.log('NOTE: reset timeout', TIMEOUT, new Date().toLocaleTimeString());
clearModalTimeout();
setModalTimeout(randomFunction);
}
Above is the logic, below is the input tag.
<input type="password" placeholder="pin/password" id="password" oncreate={element => element.focus()} onchange={() => resetModalTimeout(randomFunction)} />
The main part of this issue is, if I uncomment the console.logs, it works perfectly. The way the code is shown now, it does not work. It will only go through the First cycle (so only work for 30 seconds even though I make a change to the input). and when I log, it clearly shows that change goes through. Any ideas? Of course, I don't want the console.log in the main code, also I am using hyperapp (existing code base).
When Logging, I can see the TIMEOUT value changing as expected.
I just realized what the issue was. With more debugging, my coworker and I realized it was related with the lifecycle hook. It should be oninput rather than onchange. On my computer, onchange was working just fine when logging (not too sure why if someone has an answer to that), but not on my coworker's computer. When changed to oninput it worked just fine for us both. onchange was waiting for the focus to leave the input.
I am working with a database app and I sometimes I have to click on tens or even hundreds of same buttons on a web page so I thought I save some time and run a script in the Inspect -> Console window of the Crome browser to do the job for me. I found a script which does the job just fine, however the database app hangs up after the first 10-20 clicks so I spoke with our developers and they advised that there should be a small delay between the clicks. They were not sure how much though so I need to experiment with it. So, by now I am trying to run the following script:
javascript:var inputs = document.getElementsByClassName('BUTTON CLASS HERE');
$(function theLoop (i) {
setTimeout(function () {
inputs[i].click();
if (--i) {
theLoop(i);
}
}, 100);
})(inputs.length);
It does nothing, but gives me the following error message:
gE02JAse0g9.js:60 ErrorUtils caught an error: "Cannot read property 'click' of undefined". Subsequent errors won't be logged
There seems to be some problem with calling the inputs[i].click() within the SetTimeout function, because it works just fine if I run it in a simple for loop like this:
javascript:var inputs = document.getElementsByClassName('BUTTON CLASS HERE');
for(var i=0; i<inputs.length;i++) {
inputs[i].click();
}
What am I doing wrong?
Thanks.
inputs[inputs.length] (on your first iteration, i === inputs.length) will always be undefined - array-like objects are zero-indexed in Javascript, so when inputs[i].click(); is encountered, an error is thrown.
Either initialize i to inputs.length - 1 instead, or you might find it easier to use your original code and simply await a Promise that resolves after 100ms or so:
const resolveAfter100MS = () => new Promise(res => setTimeout(res, 100));
(async () => {
var inputs = document.getElementsByClassName('_42ft _4jy0');
for(var i=0; i<inputs.length;i++) {
inputs[i].click();
await resolveAfter100MS();
}
})();
Is there any tool (preferably extension/add-on to any browser) that allows you to see all the value changes of the desired JS variable in real time?
Previously I did something like this (in pure JS):
var someVariable;
var previousValueOfSomeVariable;
var f = function() {
if (previousValueOfSomeVariable != someVariable) {
console.log(Date.now(), someVariable);
previousValueOfSomeVariable = someVariable;
}
}
var TO = setInterval(f, 100);
It did the trick, but was, of course, inefficient (in reality the function was bigger, while it required object-copy function if variable was an object and further checks)...
UPDATE
I'm aware of console tools, but I'd like to see the history of changes, like:
someVariable
0ms: undefined;
10ms: 5;
40ms: 'someothervalue';
150ms: null
etc.
(Milliseconds are given for example purposes, not necessarily required). Maybe it can be done within the DevTools console, but I don't know how.
Chrome dev tools has functionality for this.
insert the line
debugger;
right after the variable you're interested in. When your page executes and dev tools is open it will pause there and you can inspect the console.log with the value it had at that moment.
For example - say you have an onClick handler and want to see what information is passed in the event:
html:
<input onClicked={myFunc} />
JS
function myFunc(event){
console.log(event)
}
This will log the event to the console, but if you try to drill down chrome evaluates the obj when you click on it and since its long gone, its mostly null:
However if you use debugger, chrome pauses execution when it hits that and you can dig into the real event:
JS:
function myFunc(event){
console.log(event);
debugger;
}
Lets you drill down into the object as it was at the time you hit the debugger line
More info in the chrome dev tools site:
https://developers.google.com/web/tools/chrome-devtools/javascript/breakpoints
The different DevTools (tested in Chrome DevTools, Firefox DevTools and Firebug) don't offer a way to see the value changes in real time. You always have to refresh their display manually.
Firefox offers an Object.prototype.watch() function (for other browsers there is a shim), which does what you want.
Example:
test = 0;
setInterval(() => test++, 1000);
window.watch("test", (id, oldValue, newValue) => {
console.log(new Date().toLocaleTimeString(), newValue);
return newValue;
});
This will output something like this:
09:51:03 1
09:51:04 2
09:51:05 3
09:51:06 4
09:51:07 5
Note: This function only allows to watch single properties of an object, so, in order to watch all object properties you need to loop over them and call watch() for each one.
Ah yes object.watch . It isn't used very often though! Here is a more detailed post of what I think you're looking for Listening for variable changes in JavaScript or jQuery
I have the following code which demonstrates the difference in calling a long-running function directly from an event trigger, vs. using setTimeout().
Intended behavior:
When the first button is pressed, it appears pressed, the calculation runs for several seconds, then when the calculation finishes, the button appears depressed again and the second column changes from "not calculating yet" to "calculation done". (I won't elaborate on why that is supposed to happen; it's explained in linked answer.)
When the second button is pressed, the button depresses immediately; the second column immediately changes to "calculating..." text. When the calculation finishes several seconds later, the second column changes from "calculating..." to "calculation done".
What actually happens:
This works perfectly in Chrome (both buttons behave as expected)
This works perfectly in Internet Explorer 8
This does NOT work in Firefox (v.25) as-is. Specifically, the second button behaves 100% as the first one.
Changing the timeout in setTimeout() from 0 to 1 has no effect
Changing the timeout in setTimeout() from 0 to 500 works
Which leaves me with a big conundrum.
According to the whole reason behind why setTimeout() works whereas lack of one doesn't, the delay should have zero effect on how things work, since setTimeout()'s main purpose is to change the queuing order here, NOT to delay things.
So, why is it not working with delay 0 or 1 on Firefox, but works as expected with delay 500 (and works with any delay on Internet Explorer 8/Chrome)?
UPDATE: In addition to source code below, I also made a JSFiddle. But for some reason JSFiddle refuses to even load on my Internet Explorer 8, so for that testing, the code below is required.
UPDATE2: Someone raised the possibility of there being an issue with configuration setting dom.min_timeout_value in Firefox. I have edited it from 4 to 0, restarted the browser, and nothing was fixed. It still fails with a timeout of 0 or 1 and succeeds with 500.
Here is my source code - I simply saved it to a HTML file on C: drive and opened in all three browsers:
<html><body>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<table border=1>
<tr><td><button id='do'>Do long calc - bad status!</button></td>
<td><div id='status'>Not Calculating yet.</div></td></tr>
<tr><td><button id='do_ok'>Do long calc - good status!</button></td>
<td><div id='status_ok'>Not Calculating yet.</div></td></tr>
</table>
<script>
function long_running(status_div) {
var result = 0;
for (var i = 0; i < 1000; i++) {
for (var j = 0; j < 700; j++) {
for (var k = 0; k < 200; k++) {
result = result + i + j + k;
}
}
}
$(status_div).text('calclation done');
}
// Assign events to buttons
$('#do').on('click', function () {
$('#status').text('calculating....');
long_running('#status');
});
$('#do_ok').on('click', function () {
$('#status_ok').text('calculating....');
window.setTimeout(function (){ long_running('#status_ok') }, 0);
});
</script>
</body></html>
To test, you will need to change the nested loop boundaries to 300/100/100 for Internet Explorer 8; or to 1000/1000/500 for Chrome, due to different sensitivity of "this JS is taking too long" error coupled with JavaScript engine speed.
There is a copy of the current (Jun 28, 2016) implementation of window.setTimeout() in Ubuntu.
As we can see, the timer gets inserted by this line of code:
nsAutoPtr<TimeoutInfo>* insertedInfo =
mTimeouts.InsertElementSorted(newInfo.forget(), GetAutoPtrComparator(mTimeouts));
Then a few lines below you have an if() statement:
if (insertedInfo == mTimeouts.Elements() && !mRunningExpiredTimeouts) {
...
The insertedInfo == mTimeouts.Elements() checks whether the timer that was just inserted already timed out. The following block does NOT execute the attached function, but the main loop will immediately notice that a timer timed out and thus it will skip the IDLE state (a yield of the CPU) that you are expecting.
This clearly (at least to me) explains the behavior you are experiencing. The rendering on the screen is another process (task/thread) and the CPU needs to be relinquished for that other process to get a chance to re-paint the screen. For that to happen, you need to wait long enough so your timer function does not get executed immediately and a yield happens.
As you've notice a pause of 500ms does the trick. You can probably use a smaller number, such as 50ms. Either way it is not going to guarantee that a yield happens, but chances are it will happen if the computer on which that code is running is not currently swamped (i.e. an anti-virus is not currently running full speed in the background...)
The complete SetTimeout() function from Firefox:
(location of the file in the source: dom/workers/WorkerPrivate.cpp)
int32_t
WorkerPrivate::SetTimeout(JSContext* aCx,
dom::Function* aHandler,
const nsAString& aStringHandler,
int32_t aTimeout,
const Sequence<JS::Value>& aArguments,
bool aIsInterval,
ErrorResult& aRv)
{
AssertIsOnWorkerThread();
const int32_t timerId = mNextTimeoutId++;
Status currentStatus;
{
MutexAutoLock lock(mMutex);
currentStatus = mStatus;
}
// It's a script bug if setTimeout/setInterval are called from a close handler
// so throw an exception.
if (currentStatus == Closing) {
JS_ReportError(aCx, "Cannot schedule timeouts from the close handler!");
}
// If the worker is trying to call setTimeout/setInterval and the parent
// thread has initiated the close process then just silently fail.
if (currentStatus >= Closing) {
aRv.Throw(NS_ERROR_FAILURE);
return 0;
}
nsAutoPtr<TimeoutInfo> newInfo(new TimeoutInfo());
newInfo->mIsInterval = aIsInterval;
newInfo->mId = timerId;
if (MOZ_UNLIKELY(timerId == INT32_MAX)) {
NS_WARNING("Timeout ids overflowed!");
mNextTimeoutId = 1;
}
// Take care of the main argument.
if (aHandler) {
newInfo->mTimeoutCallable = JS::ObjectValue(*aHandler->Callable());
}
else if (!aStringHandler.IsEmpty()) {
newInfo->mTimeoutString = aStringHandler;
}
else {
JS_ReportError(aCx, "Useless %s call (missing quotes around argument?)",
aIsInterval ? "setInterval" : "setTimeout");
return 0;
}
// See if any of the optional arguments were passed.
aTimeout = std::max(0, aTimeout);
newInfo->mInterval = TimeDuration::FromMilliseconds(aTimeout);
uint32_t argc = aArguments.Length();
if (argc && !newInfo->mTimeoutCallable.isUndefined()) {
nsTArray<JS::Heap<JS::Value>> extraArgVals(argc);
for (uint32_t index = 0; index < argc; index++) {
extraArgVals.AppendElement(aArguments[index]);
}
newInfo->mExtraArgVals.SwapElements(extraArgVals);
}
newInfo->mTargetTime = TimeStamp::Now() + newInfo->mInterval;
if (!newInfo->mTimeoutString.IsEmpty()) {
if (!nsJSUtils::GetCallingLocation(aCx, newInfo->mFilename, &newInfo->mLineNumber)) {
NS_WARNING("Failed to get calling location!");
}
}
nsAutoPtr<TimeoutInfo>* insertedInfo =
mTimeouts.InsertElementSorted(newInfo.forget(), GetAutoPtrComparator(mTimeouts));
LOG(TimeoutsLog(), ("Worker %p has new timeout: delay=%d interval=%s\n",
this, aTimeout, aIsInterval ? "yes" : "no"));
// If the timeout we just made is set to fire next then we need to update the
// timer, unless we're currently running timeouts.
if (insertedInfo == mTimeouts.Elements() && !mRunningExpiredTimeouts) {
nsresult rv;
if (!mTimer) {
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return 0;
}
mTimerRunnable = new TimerRunnable(this);
}
if (!mTimerRunning) {
if (!ModifyBusyCountFromWorker(true)) {
aRv.Throw(NS_ERROR_FAILURE);
return 0;
}
mTimerRunning = true;
}
if (!RescheduleTimeoutTimer(aCx)) {
aRv.Throw(NS_ERROR_FAILURE);
return 0;
}
}
return timerId;
}
IMPORTANT NOTE: The JavaScript instruction yield, has nothing to do with what I am talking about. I am talking about the sched_yield() functionality which happens when a binary process calls certain functions, such as sched_yield() itself, poll(), select(), etc.
I faced this issue with Firefox while toggling CSS classes using jQuery to control a CSS transition.
Increasing the duration of setTimeout to 50 from 0 helped, but as Alexis suggested this wasn’t 100% reliable.
The best (if longwinded) solution I found was to combine an interval timer with an IF statement to actually check whether the necessary styles had been applied before triggering the transition, rather using setTimeout and assuming execution had taken place in the intended order, e.g.
var firefox_pause = setInterval(function() {
//Test whether page is ready for next step - in this case the div must have a max height applied
if ($('div').css('max-height') != "none") {
clear_firefox_pause();
//Add next step in queue here
}
}, 10);
function clear_firefox_pause() {
clearInterval(firefox_pause);
}
In my case at least, this seems to work every time in Firefox.
In Firefox, the minimum value for setTimeout() calls is configurable and defaults to 4 in current versions:
dom.min_timeout_value The minimum length of time, in milliseconds,
that the window.setTimeout() function can set a timeout delay for.
This defaults to 4 ms (before 10 ms). Calls to setTimeout() with a
delay smaller than this will be clamped to this minimum value.
Values like 0 or 1 should behave like 4—no idea if that will cause delays in your code or just break it.