'this' is undefined in Angular, XML2JS - javascript

export class ServerComponent {
servers:string[];
getString:any;
serversJSON:any;
constructor() {
}
ngOnInit() {
console.log("ngOnInit");
this.getXmlService.getData().subscribe((getString) =>
{
xml2js.parseString(getString, function (err, result) {
this.serverJSON = result; // This doesn't work
console.log(result); // This works
});
});
}
}
In this code, the indicated line does not seem to be able to access this. Console logging shows an undefined.
result gives me a correct and formatted JSON, but when I attempt to take the result variable and set it in the this.serverJSON, it throws an error Cannot set property 'serversJSON' of undefined.
I want to take the value held in result and put it in serversJSON.
How can this be achieved and why is this not available?

You are losing the context of this within your callback function.
Use a fat-arrow function (which preserves this) instead.
xml2js.parseString(getString, (err, result) => {
this.serverJSON = result;
});

Related

Get method/function name in JavaScript class from method it self

I want to log an errors to know from which method/function of class i got error. To log this i want a generic code, by that i can know the method/function name from method it self. below is my code.
In below code, each catch block i want particular method name like SaveData and GetData.
I tried arguments.callee but it's not working in strict mode.
I also tried Object.values(this) but it gives me all methods array so i can't decide at what element my current method name exist.
I want any generic solution because i have hundreds of function in a class and i not want to write each function name in each method.
class MyClass {
/**
* Class default constructor
*/
constructor() {
this.file_path = path.join(__dirname, path.basename(__filename));
}
SaveData = async (req, res) => {
try {
//doing some operation to store data
} catch (err) {
//in catch block i want "SaveData"(method name) so i can pass as parameter in below generic method which i have created somewhere in common file.
log.error(res, err, this.file_path);
}
}
GetData = async (req,res) => {
try {
//doing some operation to get records from db
} catch (err) {
//in catch block i want "GetData"(method name) so i can pass as parameter in below generic method which i have created somewhere in common file.
log.error(res, err, this.file_path);
}
}
}
module.exports = new MyClass();

ES6 class context in NodeJs? Or using 'this' inside a class in NodeJs?'

I am new to node js and i am actually not able to understand how to call methods inside a class except statically or by creating a new object each time i'm iterating over functions.
This is kind of crazy. For example:
class UserController
{
methodOne (req, res) {
this.methodTwo (req);
}
methodTwo (data) {
return data;
}
}
That's how i want to call my function but, every time i do this, I end up with error of this is undefined.
I know fat arrow functions don't follow the same context like in javascript. But i just wanna make sure if i'm doing it right or not.
And that's how i achieve above code.
class UserController
{
static methodOne (req, res) {
UserController.methodTwo (req);
}
static methodTwo (data) {
// Manipulates request before calling
return UserController.methodThree (data);
}
static methodThree (data) {
return data;
}
}
i.e. calling each method statically with class name UserController.
So if there's any better way to do it, I need you to suggest.
Thanks in advance.
P.S: Above code is just an example guys.
The reason for your problem is that you lost the function context
class UserController {
async methodOne() {
return this.methodTwo()
}
async methodTwo() {
return Promise.resolve("methodtwo")
}
}
const obj = new UserController();
const methodOne = obj.methodOne;
methodOne(); // ----> This will throw the Error
methodOne.call(obj); // ----> This Works
// Or you can call the method directly from the obj
obj.methodOne(); // Works!!
// If you want to cache the method in a variable and preserve its context use `bind()`
const methodOneBound = obj.methodOne.bind(obj);
methodOneBound(); // ----> This works

flow error accessing optional prop after truthy check

flow 0.67.1 (but behavior continues to exist in 0.73.1)
Example:
type PropOptional = {
prop?: ComplexType
};
type ComplexType = {
callable: () => void,
anotherCallable: () => void
};
function usePropOptional(arg1: PropOptional) {
if (arg1.prop) {
arg1.prop.callable();
arg1.prop.anotherCallable();
arg1.prop.callable();
}
};
The function checks for the presence of arg1.prop before accessing any properties on arg1.prop. This should be sufficient to verify that arg1.prop is defined.
Flow is fine with the first time an arg1.prop property is accessed, which is the call to arg1.prop.callable() on the first line inside the if block. However, flow generates errors on subsequent attempts to access arg1.prop properties in the exact same if block:
arg1.prop.anotherCallable();
arg1.prop.callable();
I am forced to either prepend each line with a rote arg1.prop && truthy check, or reassign arg1.prop to a local variable inside the if block:
function usePropOptional(arg1: PropOptional) {
if (arg1.prop) {
const reallyExists = arg1.prop;
reallyExists.callable();
reallyExists.anotherCallable();
reallyExists.callable();
}
};
This doesn't feel right. What am I doing wrong or missing?
You can check this in a flow repl here on flow.org.
This is documented in FlowType's Type Refinement section:
Refinement Invalidations
It is also possible to invalidate refinements, for example:
// #flow
function otherMethod() { /* ... */ }
function method(value: { prop?: string }) {
if (value.prop) {
otherMethod();
// $ExpectError
value.prop.charAt(0);
}
}
The reason for this is that we don’t know that otherMethod() hasn’t
done something to our value.
...
There’s a straightforward way to get around this. Store the value
before calling another method and use the stored value instead. This
way you can prevent the refinement from invalidating.
// #flow
function otherMethod() { /* ... */ }
function method(value: { prop?: string }) {
if (value.prop) {
var prop = value.prop;
otherMethod();
prop.charAt(0);
}
}
So the workaround in your final case appears to be the suggested way to avoid this problem.

How to pass a parameter to a function that is passed to another function as string?

I have the following piece of code :
accountSelector.executeInParallel('processAccounts', 'postProcess');
function processAccounts() {
return JSON.stringify(syncMasterLists());
}
And instead of having this, I want to be able to pass a value to the processAccounts accounts function.
For the purpose I changed the code so it's looking like this now :
accountSelector.executeInParallel('processAccounts("DE")', 'postProcess');
function processAccounts(arg) {
return JSON.stringify(syncMasterLists());
}
Unfortunately, after introducing the change I started getting the following error :
Cannot find function processAccounts("DE").
I cannot understand am I doing this wrong(and if yes then what is wrong) or it's just something that can't be done.
I cannot understand am I doing this wrong(and if yes then what is
wrong) or it's just something that can't be done.
accountSelector.executeInParallel takes the function name as parameter and execute the same, processAccounts("DE") is not a valid function name or the name of the function that exists.
As per documentation, there is a way to pass optionalInput parameter
The input, if specified by optionalInput, will be passed into the
function specified by functionName
accountSelector.executeInParallel(functionName, optionalCallbackFunctionName, optionalInput)
In your case, it will be
accountSelector.executeInParallel('processAccounts', 'postProcess', 'DE' );
Why don't you call the function first and replace the result in the 'executeInParallel' method as follows:
var res = processAccounts("DE");
accountSelector.executeInParallel(res, 'postProcess');
function processAccounts(arg) {
return JSON.stringify(syncMasterLists());
}
Some closure can probably solve your problem, depends on how accountSelector.executeInParallel is implemented
const accountSelector = {
executeInParallel(pre, post) {
let result = eval(pre)()
eval(post)(result)
}
}
accountSelector.executeInParallel(processAccountsWithArg('Foo'), 'postProcess');
function processAccount(arg) {
console.log('processAccount', arg)
return JSON.stringify({
key: 'value'
});
}
function processAccountsWithArg(arg) {
return function() {
return processAccount(arg)
}
}
function postProcess(result) {
console.log('postProcess', result)
}

How to access an object created within a function from another function

I'm new to JavaScript and NodeJS, and I need to solve this issue quickly.
connection(getSQL2)
.then((table)=> {
table.forEach(row=> {
let obj = {
countryid: row.IdPais,
country: row.NombrePais
};
data.push(obj);
});
});
console.log(obj);
When I try to display the object using console.log, I get undefined, which seems pretty obvious. But what would be an easy way to get it to display the Object 'obj' that was created above?
UPDATE: Just to clarify, console.log is used here only as an example. I need to access the object from outside that function however I can.
Thanks in advance!
Two things going on here.
1) You're using a promise and promises asynchronously resolve. Good rule of thumb is any code that ends with .then(...) is going to be a promise. What that means is that code underneath it can execute before the promise is finished and if it reads those values before the promise has finished resolving they will be read as undefined.
2) You use the let keyword to define your variable which means it will only be defined in the scope:
row => {
let obj = {
countryid: row.IdPais,
country: row.NombrePais
};
data.push(obj);
// Show the object where it is defined
console.log(obj);
}
you can create a global variable, and assign the value to that variable inside the that function.
Then, you will be able to access the variable obj outside the function also.
var temp;//declare a global variable here.
connection(getSQL2)
.then((table)=> {
table.forEach(row=> {
let obj = {
countryid: row.IdPais,
country: row.NombrePais
};
data.push(obj);
temp = obj;//assign value to global variable here
});
});
console.log(temp);//you can access the 'obj' using temp
Hope this helps you.
You need to do this:-
async database()
{
try {
const table= await connection(getSQL2);
if (table!== null)
{
table.forEach(row=> {
let obj = {
countryid: row.IdPais,
country: row.NombrePais
};
console.log('This will resolve the promise',obj);
}
else
{
//anything needed
}
}
catch (error)
{
// Error retrieving data
}
}
async and await are the keywords used in parallel. await keyword will not allow the control to go down until data is fetched.

Categories