Named vs anonymous functions different behavior with a promise - javascript

I ran into a bug which I finally solved, but why it happen(ed/s) is still beyond me.
I save a variable foo using browser.storage.local.set for a firefox addon that I'm developing. I know that the variable is set, and the apparent bug was relying on some small piece of code that leads to this:
browser.storage.local.get((val) => {
if (val['foo'] === undefined){
console.log('Undefined');
}
else {
console.log('Defined')
}
});
// Outputs `Defined`, which is correct.
However, if I define the callback first, and then I get wrong output.
function checkStoredSettings(val) {
if (val['foo'] === undefined) {
console.log('Undefined')
}
else {
console.log("Defined")
}
}
browser.storage.local.get().then(checkStoredSettings, console.log);
// Outputs `Undefined`, which is incorrect.
//UPDATE
browser.storage.local.get(checkStoredSettings);
// Outputs `Undefined`, which is also incorrect.
Can someone explain what am I not getting here? I have now run the above two codes sequentially (in both orders) in the same scope.

Did you tried something like that ?
browser.storage.local.get('foo').then(console.log)

Related

How to know whether a piece of JS is executed in an ES Module or a regular script?

I want to know whether a piece of JavaScript is executed in an ES module or a simple script.
This is what I tried so far:
function isEsm1() {
try {
// Script gives a syntax error during parsing when script is not an esm
return Boolean(import.meta.url);
} catch(err) {
return false;
}
}
function isEsm2() {
// will always return false, because `eval` always seems to be executed in regular script context
try {
return eval('Boolean(import.meta.url)');
} catch(err) {
return false;
}
}
function isEsm3() {
// Of course doesn't work, but had to try 😉
return 'meta' in import;
}
Is the regular script executed in the browser or in another context?
In a browser, how about:
var anyvar = {};
var inModule = anyvar === window.anyvar;
If you're in a module, you are not declaring anything on the window...
In NodeJS you could do something similar with global or this:
let inModule = this === module.exports..
Did not try it yet.. but should work I guess...
After testing, just the check for this === undefined is enough to test if you're executing in or out of a module..
Inside a module, this is undefined (as per spec). In global scope this points to global this, which is the window object in the case of a browser context...
Thanks to the discussion in John Gorter's answer, I think we've found a way.
console.log('In module: ' + (this === undefined));
It's as simple as that. Inside a module (and only inside a module (I hope)), this will be undefined. I found it in the v8 documentation here: https://v8.dev/features/modules#intro

Javascript Element Validation within If-Statement

I'm having issues when adding an element validation within an if-statement.
Basically, irrelevant of the result of the if-statement, Protractor is still trying to find the element specified within the if-statement.
Here is the code that is still running even though the if-statement returned false:
if (thisIsAlwaysFalse == true) {
console.log(':::::::::::::::' + thisIsAlwaysFalse);
it('If-statement test', function(done) {
var elementToFind = element(by.xpath('//td[contains(#class,"hello")]'));
browser.wait(function() {
return browser.isElementPresent(elementToFind);
}, 5000);
elementToFind.click();
done();
});
}
Also, funny thing is that the console.log part is successfully ignored!
Anyone has a solution for this or possibly knows why this is happening?
Thanks in advance :)
Have you debugged the problematic area?
Nevertheless, your always-false statement is probably a promise, which is always a truthy value. In order to solve it, you need to put the whole block to then callback.
For example:
doStuff()
.then(function (result) {
if (yourAlwatsFalsyCondition(result) {
return elementFindYouDid(results)
.moreStuff(doMore);
}
})

What is the current best way to wrap console.log() that will preserve line numbers?

I've previously used the following based on other SO answers (without really understanding the need for (nor the workings of) the prototype.apply.apply
var mylogger = {
log: function () {
if (window.console) {
if (window.console.log) {
Function.prototype.apply.apply(console.log, [console, arguments]);
}
}
},
...
};
while this prevents IE from crapping on itself, it also make the line number reporting unusable (it always reports the apply.apply.. line.
I was playing around a little and discovered that the following seems to do exactly what I need, i.e. prevent IE from crapping on itself and report the line number where mylogger.log(..) was called from..
var mylogger = {
// function invocation returning a safe logging function..
log: (function () {
if (window.console && window.console.log && Function.prototype.bind) {
return window.console.log.bind(window.console);
} else {
return function () {};
}
}()),
...
};
I've done some basic testing on IE/FF/Chrome without seeing any issues.. is this reasonable or is there a better way?
What you're doing is fine I guess, but if you aren't adding any additional functionality, you could do something simple and in one line:
window.console = (window.console || {debug:function(){},log:function(){},error:function(){}});
You could, of course, add other console functions if you use them.

call function using if statement

I want to be able to call a function within an if statement.
For example:
var photo = "yes";
if (photo=="yes") {
capturePhoto();
}
else {
//do nothing
};
This does nothing though. The function is clearly defined above this if statement.
Edit: Wow, downboated to hell! capturePhoto(); was just an example function that didn't really need any more explanation in this scenario?
That should work. Maybe capturePhoto() has a bug?
Insert an alert() or console.log():
var photo = "yes";
if (photo == "yes") {
alert("Thank you StackOverflow, you're a very big gift for all programmers!");
capturePhoto();
} else {
alert("StackOverflow.com must help me!");
}
I'm not seeing any problems here. I used this code and the function call worked. I kept your code and just added a function called capturePhoto().
Are you sure that the code you're using to call the function is firing?
var photo = "yes";
if (photo=="yes")
{
capturePhoto();
}
else
{
//do nothing
};
function capturePhoto()
{
alert("Pop up Message");
}
You probably missed something, a quotation, a semicolon or something like that. I would recommend you to use a debugger like Firebug or even Google Chrome's Web Developer Tool. You will know what's wrong with your code and where it is wrong.
You may take a look at this live code that your code above works: http://jsfiddle.net/ZHbqK/
The code looks fine to me (except you don't need the ; at the end of the last line). Check your error log; perhaps the browser thinks capturePhoto is not defined for some reason. You can also add alert statements to make sure the code is actually running:
var photo = "yes";
alert('Entering if statement');
if (photo=="yes") {
alert('then');
capturePhoto();
} else {
alert('else');
//do nothing
}
When you encounter a situation where it seems like a fundamental language feature is not working, get some more information about what is going on. It is almost never the platform's fault. It is occasionally a misunderstanding of how the feature works (e.g. why does parseInt('031') == 25 ?). It is usually a violation of an assumption you're making about the code that isn't holding up because of a problem elsewhere.
You should also consider using true and false instead of strings that could be manipulated depending on input.
If I had to correct the following code, then I should've done it like this;
var photo = true; // Will capture picture.
if (photo) { // 'true' is a truthy value.
capturePhoto();
} else {
// Do nothing
}
The code that you posted does work.
I copied it and tested it.
Demo: http://jsfiddle.net/Guffa/vraPQ/
The only thing wrong with it that I can see is a semicolon after the closing bracket, but that is only a style problem. It will form an extra empty statement, but that doesn't cause any problems.

call future javascript function compatibility on all browsers?

let say i have function like below
function doSomethingNow(){
callSomethingInFutureNotExistNow();
}
at the moment doSometingNow() is created callSomethingInFutureNotExistNow() not exist yet. It will be created in the future, on firefox, this doesn't show any error on firebug. Will these kind of function compatible on all browsers without throwing errors ?
Since javascript isn't compiled you shouldn't ever receive any errors with the code you posted assuming you don't call doSomethingNow() before callSomethingInFutureNotExistNow is declared.
To be safe though, you may want to do some null checking
function doSomethingNow(){
if (callSomethingInFutureNotExistNow) {
callSomethingInFutureNotExistNow();
}
}
Or if you want to be even more strict you can do type checking like this
function doSomethingNow(){
if (typeof(callSomethingInFutureNotExistNow) === 'function') {
callSomethingInFutureNotExistNow();
}
}

Categories