I've identified a bug where the performance.now() API's for IE 11 return Infinity. I've noticed this only happens when the following registry key is set:
[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Main]
"TabProcGrowth"=dword:00000000
I've repro'd this on Win10 and Server 2016. Is there a workaround?
You can replace performance.now() with your own function based on Date.now(). You lose the benefits of the API (such as sub-millisecond precision and the monotonically increasing clock) but code that depends on performance.now() should be indifferent to the change.
// Run this as early as possible for the most accurate start time
(function() {
if(!isFinite(performance.now())) {
var start = Date.now();
performance.now = function() { return Date.now() - start; }
}
})();
Related
I am debouncing a method and wanted to know if it's possible to process it at least once while it's actively being debounced.
Example: The debounce wait is set to 1 second, and during 10 seconds straight, the function is being called actively (more often than 1 second, resulting in the function still not invoked yet). Could I at least run the function once say at the 5th second? So I do not have to wait till 10s fully pass before it runs finally once.
My fear is that if the process is "busy" and constantly bombarded by requests, I would still like to process something.
Not sure if it's relevant, but this is part of React Native.
Debouncing partially blocks unnecessary requests but does not guarantee that new requests will not be dispatched while the system is busy.
We should implement a mechanism to detect if the system is busy or not then we decide to dispatch a new request.
import debounce from "lodash/debounce";
function Component() {
// Detect the status of an expensive operation
let operationRunning = false;
const runExpensiveOperation = () => {
// If expensive operation still running, discard dispatching
// new operations
if (operationRunning) {
return;
}
operationRunning = true;
/** Do expensive operations here - Writing, reading
from database or compress files,... **/
operationRunning = false;
};
const debounceExpensiveOperation = debounce(runExpensiveOperation, 1000);
// ássign debounced function for the event handler
}
It always worked before, but it is no longer working.
I have a rate limiting logic, but even if I clear all rate limiting data, it still happens. Only with a specific user.
I created another account on FaunaDB for testing purposes and a new database. If I restore the old database data to that new database, everything works!
So I recreated the entire database on the old FaunaDB account and the problem persists.
Is anyone experiencing something similar?
Is there any information in cache?
Login(Match(Index("accounts_by_email"), "email#email.com"), {
password: "secret",
})
/* returns
Error: [
{
"position": [],
"code": "authentication failed",
"description": "The document was not found or provided password was incorrect."
}
]
*/
The password is not incorrect. It works on the other FaunaDB account with the data restored.
./fdm -source path=backup -dest key={admin_key}
Yes, that was a temporary problem. I experienced it was well at a certain moment in my own Fwitter example. Our uniqueness detection didn't play well with code that created/updated/deleted things in one complex FQL flow which the code is doing :). I ticketed that and it should be fixed in the meantime.
It's good to know that the rate limiting in there was a bit me experimenting with events. It can also be written much simpler, I guess I was a bit to deep zoned and to be fair.. I just joined FaunaDB back then. I'm working on a skeleton app that will contain that simpler version. In the meantime here is the code:
Simpler rate limiting
import { rateLimiting } from '../../fauna-queries/helpers/errors'
import faunadb from 'faunadb'
/*
* Ideally we limit the amount of calls that come to Login.
*/
const q = faunadb.query
const {
If,
Epoch,
Match,
Index,
Collection,
Let,
Var,
Paginate,
Select,
TimeDiff,
Or,
GTE,
Abort,
Create,
IsEmpty,
Count,
LT,
Do,
Now,
Subtract
} = q
function AddRateLimiting(action, FqlQueryToExecute, Identifier, calls, perMilliseconds) {
const ExecuteAndCreateLog = Do(
Create(Collection('logs'), {
data: {
action: action,
identity: Identifier
}
}),
FqlQueryToExecute
)
return Let(
{
logsPage: Paginate(Match(Index('logs_by_action_and_identity_ordered_by_ts'), action, Identifier), {
size: calls
})
},
If(
Or(IsEmpty(Var('logsPage')), LT(Count(Select(['data'], Var('logsPage'))), calls)),
// If no logs exist yet, create one.
ExecuteAndCreateLog,
Let(
{
// the page looks like { data: [timestamp1, timestamp2,...]},
// we will retrieve the last timestamp of that page. If the pagesize would be 3, it would be the oldest of these 3 events.
// since the index is ordered from new to old.
timestamp: Select(['data', Subtract(calls, 1)], Var('logsPage')),
// transform the Fauna timestamp to a Time object
time: Epoch(Var('timestamp'), 'microseconds'),
// How long ago was that event in ms
ageInMs: TimeDiff(Var('time'), Now(), 'milliseconds')
},
If(
GTE(Var('ageInMs'), perMilliseconds),
// Then great we execute
ExecuteAndCreateLog,
// Else.. Abort! Rate-limiting in action
Abort(rateLimiting)
)
)
)
)
}
Blocking after faulty logins
I also separated blocking three faulty logins since I was kinda abusing that rate-limiting system for it. A few undefines in this code of course, it's just meant to give you an idea of how it looks for more info, keep an eye out for the skeletons + blogs to come out.
// Let's wrap some other functionality around the login.
const BlockThreeFaultyLogins = Do(
If(
GTE(Count(Match(Index('logs_by_action_and_identity'), 'faulty_login', email)), MAX_LOGIN_ATTEMPTS),
// Abort if exceeded
Abort(tooManyFaultyLogins),
// Else, just continue as usual!
Let(
{
login: LoginFQL
},
Do(
If(
Equals(false, Var('login')),
// if the login is faulty, we'll add a log entry
Create(Collection('logs'), {
data: {
action: 'faulty_login',
identity: email
}
}),
// Else, we will clean up the faulty_login logs
q.Map(
Paginate(Match(Index('logs_by_action_and_identity'), 'faulty_login', email)),
Lambda(['logRef'], Delete(Var('logRef')))
)
),
Var('login')
)
)
)
)
I need a repetitive block like while() that verifies a condition before being executed. My code is below, but the while doesn't work...
var foundPersonen = true;
while (foundPersonen) {
detailPage.getAllPersonen().then(function(value) {
if (value.length == 0) {
foundPersonen = true;
remoteControl(Keys.HK_BACK);
remoteControl(Keys.HK_P_up);
remoteControl(Keys.HK_INFO, 1, 3000);
}
else {
foundPersonen = false;
}
});
}
How can I replace the while but still have the same result I need?
I agree at least partially with alecxe. Some "wait" order should fix that. I just would like to explain my thought, hoping that it will be useful for you... Because I have spent a lot of time on this kind of problem^^.
The big point to me is that Protractor runs everything asynchronously.
When you run your test, Protractor basically runs every part of your code it can, i.e. until it encounters a promise. When it encounters a promise, Protractor could do two things, depending whether you have set browser.ignoreSynchronization = true; (this is my case)
If it's true, Protractor creates a new thread and wait for the promise to be resolved, but in the "main thread" Protractor continues to execute your code. If you want Protractor to wait for something, you will have to write it explicitly.
If it's false (this is the case by default), Protractor will add a browser.waitForAngular before continuing. But of course you can always add explicit waiting orders in your code, and you might want to do it in some cases to get a more stable code.
If you want more information about this, read this post
var foundPersonen = true;
while (foundPersonen){
detailPage.getAllPersonen().then(function(value) {
if (value.length == 0) {
foundPersonen = true;
remoteControl(Keys.HK_BACK);
remoteControl(Keys.HK_P_up);
remoteControl(Keys.HK_INFO, 1, 3000);
}
else {
foundPersonen = false;
}
}
In my case (browser.ignoreSynchronization = true;), this is what happens :
allocate one bit of memory for a boolean and set the value to 1;
evaluate the bit
If it is 1
Create a thread. In this thread, create a promise and wait for it to be resolved, then do something with the value of the promise
In the main thread, return to step 2
if it is 0, continue
This interpretation leads to a simple prediction. As the code that sets the value of the boolean to 0 is treated after the promise is resolved, this piece of code will create promises as fast as it can until one of these promises will be resolved and set the boolean to false.
The result of this ? Your code will reach the maximum of memory before the first promise will be resolved. --> You will receive some exception related to the allocation of memory.
I tested that with this code:
return scenariiSteps.AtlasLogin("my", "credentials")
.then(function () {
var foundDialogs = element.all(by.xpath("//div[#dialog-id]"));
var foundDialogsZero = true;
while (foundDialogs) {
foundDialogs.count().then(function (value) {
if (value == 0) {
foundDialogsZero = true;
console.log("0, man")
}
else {
console.log("Found something!")
foundDialogsZero = false;
}
});
}
});
What this code do is
Login
Allocate memory for some object (it will stock the list of the dialogs in the page of my app)
Allocate one bit of memory for a boolean and set it to false.
Evaluate the bit
if it is 1
create a promise and wait for it to be resolved, then do something with the value of the promise
return to step 4
And, to be sure of my interpretation, please note that my app contains 2 dialogs as soon as the user is logged in.
As I thought, I received FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory
"Ok, thank you for that long explanation, but... What should I do now ?"
Well basically you have to tell to Protractor to wait for some condition before performing the action you want. The best way to do it depends on your requirements and your environment. For instance, I don't think the solution of alecxe would fix the problem in my environment.
It would be useful to know a bit more about what you want to do if you want more help.
Yeah, since protractor keep adding everything on to controlflow, blocks like while do not work as expected. Try calling it recursively in a function.
function keepChecking(){
while (foundPersonen) {
detailPage.getAllPersonen().then(function(value) {
if (value.length == 0) {
foundPersonen = true;
remoteControl(Keys.HK_BACK);
remoteControl(Keys.HK_P_up);
remoteControl(Keys.HK_INFO, 1, 3000);
keepchecking();
}
else {
foundPersonen = false;
}
});
}
}
keepchecking();
I think you can solve it with browser.wait():
browser.wait(function () {
return detailPage.getAllPersonen().count().then(function (count) {
if (count == 0) {
remoteControl(Keys.HK_BACK);
remoteControl(Keys.HK_P_up);
remoteControl(Keys.HK_INFO, 1, 3000);
return false;
}
else {
return true;
}
}
}, 10000);
This would execute the condition function up to 10 seconds while the count is 0. If it is 0, it executes your remote control functions. Please test.
I am using a feature layer in JSAPI, where I edit a feature by the standard selection, change attributes, applyEdits process. It seems that there is a bug in JSAPI both 3.12 and 3.14 which makes the apply edits fail on certain features. The callback just errors out without any clue.
The interesting observations:
Failure only happens on certain features and all cases belong to a particular layer (other features in that layer are just fine).
Changing from 3.12 to 3.14 the features that cause the error are changed but did not go away.
Here is a quick snippet of the code:
sq = buildSelectionQuery();
if (sq) {
all(assetsFeatureLayers.map(function (l) { return l.selectFeatures(sq, esri.layers.FeatureLayer.SELECTION_NEW).promise;})
).then(function (fls) {
console.log('sel res', fls);
all(fls.map(function (r, i) {
var fs = r[0]; // the first is an array of selected features
var l = assetsFeatureLayers[i];
console.log(fs);
if (fs.length > 0) {
console.log("Switching phases to: ", tph);
fs.forEach(function (f) {
f.attributes['phasecode'] = tph;
});
console.log("Saving switched phases for layer: ", l.name);
return l.applyEdits(null, fs, null); //.promise;
} else {
return null;
}
})).then(function (l) {
console.log("Phase switching finished successfully!", l);
clearAllSelections();
}, function (e) {
console.log("Error switching phases!", e);
clearAllSelections();
});
});
}
OK, I found the root cause. We are using ESRI's PHP proxy, and it was a bug in that. Upgrading to the latest 1.1 beta solved the issue. Here is the link to their repo: https://github.com/Esri/resource-proxy
I made a simple website with javascript on it that calls to:
navigator.geolocation.getCurrentPosition(show_map, show_map_error);
I have put the website on the internet. I tried to open the website from different PCs (no GPS gadget) on different locations. One from my home, one from a friends office.
But the script does not always get a position.
What would be a problem?
Thank you.
The method is not guaranteed to return a position, especially if there is no GPS attached.
You could try getting a cached position instead. See the following from the API specification
// Request a position. We only accept cached positions, no matter what
// their age is. If the user agent does not have a cached position at
// all, it will immediately invoke the error callback.
navigator.geolocation.getCurrentPosition(successCallback,
errorCallback,
{maximumAge:Infinity, timeout:0});
function successCallback(position) {
// By setting the 'maximumAge' to Infinity, the position
// object is guaranteed to be a cached one.
// By using a 'timeout' of 0 milliseconds, if there is
// no cached position available at all, the user agent
// will immediately invoke the error callback with code
// TIMEOUT and will not initiate a new position
// acquisition process.
if (position.timestamp < freshness_threshold &&
position.coords.accuracy < accuracy_threshold) {
// The position is relatively fresh and accurate.
} else {
// The position is quite old and/or inaccurate.
}
}
function errorCallback(error) {
switch(error.code) {
case error.TIMEOUT:
// Quick fallback when no cached position exists at all.
doFallback();
// Acquire a new position object.
navigator.geolocation.getCurrentPosition(successCallback, errorCallback);
break;
case ... // treat the other error cases.
};
}
function doFallback() {
// No cached position available at all.
// Fallback to a default position.
}