Javascript property function execution - javascript

I have an model Object. One of the properties is a function to connect to an api and retrieve some values. I may have this out of order or need to create some sort of "Helper" function to do this correctly but I wanted to ask this question first.
var BuildInfo = {
arch: function getArch(){
// connect to api and return values
}
}
module.exports = BuildInfo;
How can I get this populate the arch property or do I need getArch function somewhere else and just return the results as an array to the arch property?

One strange idea comes to mind, if you really want something that looks like a property but is actually an asynchronous function call. Within an async function, you can var array = await BuildInfo.arch, assuming it looks like this:
var BuildInfo = {
get arch() {
// connect to api and return values
return someAsynchronousAPIThatReturnsAPromise()
}
}
module.exports = BuildInfo;
Demo
var BuildInfo = {
get arch() {
return Promise.resolve(['arch', 'info', 'array'])
}
}
async function getMyArchInfo() {
var array = await BuildInfo.arch
console.log(array)
}
getMyArchInfo()

Related

How to include or detect the name of a new Object when it's created from a Constructor

I have a constructor that include a debug/log code and also a self destruct method
I tried to find info on internet about how to detect the new objects names in the process of creation, but the only recommendation that I found was pass the name as a property.
for example
var counter = {}
counter.a =new TimerFlex({debug: true, timerId:'counter.a'});
I found unnecessary to pass counter.a as a timerId:'counter.a' there should be a native way to detect the name from the Constructor or from the new object instance.
I am looking for something like ObjectProperties('name') that returns counter.a so I don't need to include it manually as a property.
Adding more info
#CertainPerformance What I need is to differentiate different objects running in parallel or nested, so I can see in the console.
counter.a data...
counter.b data...
counter.a data...
counter.c data... etc
also these objects have only a unique name, no reference as counter.a = counter.c
Another feature or TimerFlex is a method to self desruct
this.purgeCount = function(manualId) {
if (!this.timerId && manualId) {
this.timerId = manualId;
this.txtId = manualId;
}
if (this.timerId) {
clearTimeout(this.t);
this.timer_is_on = 0;
setTimeout ( ()=> { console.log(this.txtId + " Destructed" ) },500);
setTimeout ( this.timerId +".__proto__ = null", 1000);
setTimeout ( this.timerId +" = null",1100);
setTimeout ( "delete " + this.timerId, 1200);
} else {
if (this.debug) console.log("timerId is undefined, unable to purge automatically");
}
}
While I don't have a demo yet of this Constructor this is related to my previous question How to have the same Javascript Self Invoking Function Pattern running more that one time in paralel without overwriting values?
Objects don't have names - but constructors!
Javascript objects are memory references when accessed via a variables. The object is created in the memory and any number of variables can point to that address.
Look at the following example
var anObjectReference = new Object();
anObjectReference.name = 'My Object'
var anotherReference = anObjectReference;
console.log(anotherReference.name); //Expected output "My Object"
In this above scenario, it is illogical for the object to return anObjectReference or anotherReference when called the hypothetical method which would return the variable name.
Which one.... really?
In this context, if you want to condition the method execution based on the variable which accesses the object, have an argument passed to indicate the variable (or the scenario) to a method you call.
In JavaScript, you can access an object instance's properties through the same notation as a dictionary. For example: counter['a'].
If your intent is to use counter.a within your new TimerFlex instance, why not just pass counter?
counter.a = new TimerFlex({debug: true, timerId: counter});
// Somewhere within the logic of TimerFlex...
// var a = counter.a;
This is definitely possible but is a bit ugly for obvious reasons. Needless to say, you must try to avoid such code.
However, I think this can have some application in debugging. My solution makes use of the ability to get the line number for a code using Error object and then reading the source file to get the identifier.
let fs = require('fs');
class Foo {
constructor(bar, lineAndFile) {
this.bar = bar;
this.lineAndFile = lineAndFile;
}
toString() {
return `${this.bar} ${this.lineAndFile}`
}
}
let foo = new Foo(5, getLineAndFile());
console.log(foo.toString()); // 5 /Users/XXX/XXX/temp.js:11:22
readIdentifierFromFile(foo.lineAndFile); // let foo
function getErrorObject(){
try { throw Error('') } catch(err) { return err; }
}
function getLineAndFile() {
let err = getErrorObject();
let callerLine = err.stack.split("\n")[4];
let index = callerLine.indexOf("(");
return callerLine.slice(index+1, callerLine.length-1);
}
function readIdentifierFromFile(lineAndFile) {
let file = lineAndFile.split(':')[0];
let line = lineAndFile.split(':')[1];
fs.readFile(file, 'utf-8', (err, data) => {
if (err) throw err;
console.log(data.split('\n')[parseInt(line)-1].split('=')[0].trim());
})
}
If you want to store the variable name with the Object reference, you can read the file synchronously once and then parse it to get the identifier from the required line number whenever required.

Compare functions in Javascript

I have an API that takes a function as an input, and then inside the API, the intent is to add the function to an Array if the function is not already added to the Array.
The call to the API is of the form:
myApiHandle.addIfUnique(function(){
myResource.get(myObj);
});
The API is:
myApiHandle.addIfUnique(myFunc) {
if (myArray.indexOf(myFunc) === -1) {
return;
}
// add to array
}
Now this obviously does not work as expected, since each time a new function is being passed in.
My Question is: Is there a way to pass in a function into the myApiHandle.addIfUnique call that will allow me to compare the existing functions in the array with this function that is currently passed in? The comparison should compare the function name and the object, and if both are the same, then not add the function to the array. I want to avoid adding another argument to the addIfUnique call if at all possible.
In other words, is the below possible:
myApiCall.addIfUnique (someFunc) {
}
If so, what is the someFunc. And what would be the logic inside the API to detect if the function already exists in myArray?
The same problem occurs with addEventListener and removeEventListener, where the callback must be identical (in the === sense) for removeEventListener to remove it.
As you've found, obviously if you call addIfUnique like this:
addIfUnique(function() { })
the function passed each time will be a unique object. The solution is to create the function once:
var fn = function() { };
addIfUnique(fn);
addIfUnique(fn);
A related problem occurs when the function being passed in is a method invocation, so I need to bind it:
var x = { val: 42, method: function() { console.log(this.val); } };
I want to pass a bound version of it, so
addIfUnique(x.method.bind(x));
addIfUnique(x.method.bind(x));
But again, each call to x.method.bind(x) will return a separate function. So I need to pre-bind:
var boundMethod = x.method.bind(x);
addIfUnique(boundMethod);
addIfUnique(boundMethod);
First of all, comparing functions is meaningless, even if two functions are literally different, they may be functionally the same.
And for your problem, you can compare whether it's exactly the same object, or you can compare it literally by using toString() function and regExp.
var addIfUnique = (function() {
var arr = [];
return function(func) {
if (~arr.indexOf(func)) return false;
var nameArr = [];
var funcName = func.name;
var funcRegExp = new RegExp('[^\{]+\{(.+)\}$', 'i');
var funcStr = func.toString().match(funcRegExp);
funcStr = funcStr && funcStr[1];
if (!funcStr) return false;
var strArr = arr.map(function(v){
nameArr.push(v.name);
return v.toString().match(funcRegExp)[1];
});
if (~strArr.indexOf(funcStr) && ~nameArr.indexOf(funcName)) return false;
arr.push(func);
};
}());

How do I set up a class structure in Google Apps Script?

This seems like a very basic question. But how do I create a class structure within Google Apps Script?
Lets say I want to call: myLibrary.Statistics.StandardDeviation(). I have to instead call: myLibrary.StandardDeviation().
I cannot seem to break it down any further, or organize it into classes.
How can I do this?
I suspect there's something more that you're not telling us about your situation. It is possible to set up a function as a property of an object that is itself a property of an object, and thus support the calling structure you've described.
function test() {
Logger.log( myLibrary.Statistics.StandardDeviation([5.3,5.2,5,2.0,3.4,6,8.0]) ); // 1.76021798279042
};
myLibrary.gs
var myLibrary = {};
myLibrary.Statistics = {}
myLibrary.Statistics.StandardDeviation = function( array ) {
// adapted from http://stackoverflow.com/a/32201390/1677912
var i,j,total = 0, mean = 0, diffSqredArr = [];
for(i=0;i<array.length;i+=1){
total+=array[i];
}
mean = total/array.length;
for(j=0;j<array.length;j+=1){
diffSqredArr.push(Math.pow((array[j]-mean),2));
}
return (Math.sqrt(diffSqredArr.reduce(function(firstEl, nextEl){
return firstEl + nextEl;
})/array.length));
}

How to update global object

Iam trying to run an external function inside nightmarejs evalute function...As you can see my code below...
function get_my_links(url){
vo(function* () {
var nightmare = Nightmare();
var href_link = []; // i have tried making it as global without var but did not work
var title = yield nightmare
.goto('https://examply/'+url)
.evaluate(function (href_link,url,get_my_links) {
$('.myclass').each(function() {
href_link.push($(this).attr("href"));
});
if($.isNumeric($("#someid").val()))
{
get_my_links(1)
}
else{
return href_link;
}
},href_link,url);
console.log(title);
yield nightmare.end();
})(function (err, result) {
if (err) return console.log(err);
});
}
get_my_links(0)
By above code I am trying to update href_link ...
1) How to make it Global object,so that everytime the function is called new value should be added with the existing values?
1st The reason
// i have tried making it as global without var but did not work
is not working because though you making the object global but every time you call get_my_links function, it will update the global object to empty array.
For your use case, define href_link before defining get_my_links function. Like
var href_link =[];
function get_my_links() {
...
}
Defining href_link after function definition like ->
function get_my_links() {
...
}
var href_link =[];
will throw an error of undefined value of href_link inside get_my_links function due to hoisting which must be the case you have mentioned in above comment.
electron uses node.js, so you can use the global object of node.js to store the value.
https://nodejs.org/api/globals.html#globals_global
When you use this solution you should be able to access the value also from other parts of your app.

Intern: Chaining operations not returning promise

Using Intern I have to get an hidden json object from the page and then build a dictionary. After this, querying this dictionary I should perform an other action on the DOM.
The problem is that I do not know how to bind these 2 things, because I want the second operation is executed after the first one is completed.
My code is something like:
var self._formMap = null;
if(self._formMap === null || Object.keys(self._formMap).length === 0) {
return remote.findByXpath(selector)
.getAttribute('value')
.then(function(value) {
var jsonValue = JSON.parse(value);
var formMap = {};
for (var item in jsonValue) {
if (jsonValue.hasOwnProperty(item)) {
var key = jsonValue[item][0].split(/[\/]+/).pop();
formMap[key] = item;
}
}
return formMap;
}).then(function (map) {
self._formMap = map;
return _super_.setInputInForm.call(this, [..., formMap, ..]); // function in another file, but that shares the same remote object.
});
}
In the second step, when I call the setInputInForm, it's like the remote is undefined. Is it maybe because I'm returning the formMap in the first step? Could be a problem of promise?
Furthermore, I would like to isolate the first steps, and put it into a function, always returning a promise.
Thanks.

Categories

Resources