React Native function calls not working – can’t find `this.function2` - javascript

I cannot get this working. It might be simple but there is just no information online that works.
Here is what I am trying to do.
class Test {
componentDidMount() {
this.function1();
}
function1() {
var myListener = listener.on(something) {
console.log('function1 triggered');
key = 'djh3489739082';
name = 'gary';
email = 'gary#email.com';
this.function2(key, name, email);
}
}
function2 = ({ key, name, email }) => {
console.log('key: ' + key);
console.log('name: ' + name);
console.log('email: ' + email);
}
}
That's basically it. The error I get in the console is that it can't find variable this.function2.
It doesn't work when I try removing the this. prefix. I also have a much simpler function call in my code that works fine like this:
function3() {
// Some code here
this.function4();
}
function4() {
// Do some things.
}
And function3 calls function4 without issue. It's just because I need to pass parameters that it falls over and like NO ONE online needs to do this, apparently. The only examples I have found use const before the function. So like:
const function2 = ({ parameter1, parameter2, parameter3 }) => {
But this immediately throws an error. I can't use const or var or any of that stuff.
This should be easy, surely! Any ideas?

Here's what's wrong in your code. How many parameters does your function2 take? One, not three, but one. It takes a JSON object as a parameter, who has 3 properties: key, name and email, because you wrapped them with {}, but when you call it in function1, you passed 3 parameters to it, without the {}, which makes it not a JSON object.
So, you can either:
// Don't modify function2 but change function1 like so
function1() {
this.function2({ key, name, email })
}
or
// Don't modify function1 but change function2 like so
function2(key, name, email) {
}

Related

How would I programmatically call an object method? Like MyObject.XVariable(//some function)

I have an object, that takes input from an API call to fill it up.
let MyDog = {
Name: 'Dog',
}
let arrayFunctions;
fetchDogsFunctions(dogAPIUrl).then(res => {
//results is an array that has a list of functions the dog has, like //getStats(), or walkDog()
arrayFunctions = res;
})
Now I want to map through the array results and call the function on my dog like...
arrayFunctions.map(item => {
await MyDog.item(//Params)
})
How can I do this??
Where MyDog is set up from a file, and then depending on the array functions, for each function it programmatically fills in the call to the new function like MyDog.item where item is a variable in an array called "Walk()"
I assumed how your data might have structured. Pls take a look below and you might get the idea of how to call functions dynamically using "await"
const MyDog = {
funA(a) { return Promise.resolve('Function A called with parameter ' + a) }
, funB(b) { return Promise.resolve('Function B called with parameter ' + b) }
}
const arrayFunctions = ['funA', 'funB']
Promise.all(arrayFunctions.map(async (item, i) =>
await MyDog[item](++i))
)
.then(console.log)
I can't see any property name "item" in your MyDog Object
The answer is to do :
MyDog[item]()
within the loop.
I was asking the correct syntax to perform this operation

Call function from another function with parameters passed from both functions

I have this load-more listener on a button that calls the functions and it works fine.
let moviesPage = 1;
let seriesPage = 1;
document.getElementById('load-more').addEventListener('click', () => {
if (document.querySelector('#movies.active-link')) {
moviesPage++;
getMovies(moviesPage);
//getMovies(genreId, moviesPage);
} else if (document.querySelector('#series.active-link')) {
seriesPage++;
getSeries(seriesPage);
}
});
Now I have another listener on a list of links that calls the following code. It takes the genreId from the event parameter to sent as an argument to the api call. Also works fine so far.
document.querySelector('.dropdown-menu').addEventListener('click',
getByGenre);
function getByGenre (e) {
const genreId = e.target.dataset.genre;
movie.movieGenre(genreId)
.then(movieGenreRes => {
ui.printMovieByGenre(movieGenreRes);
})
.catch(err => console.log(err));
};
What I want to do is to call getByGenre from the load-more listener while passing also the moviesPage argument as you can see on the commented code so it can also be passed to the api call.
What would be the best way to do that? I've looked into .call() and .bind() but I'm not sure if it's the right direction to look at or even how to implement it in this situation.
Short Answer
Kludge: Global State
The simplest, though not the most elegant, way for you to solve this problem right now is by using some global state.
Take a global selection object that holds the selected genreId. Make sure you declare the object literal before using it anywhere.
So, your code might look something like so:
var selection = { };
document.querySelector('.dropdown-menu').addEventListener('click',
getByGenre);
function getByGenre (e) {
const genreId = e.target.dataset.genre;
selection.genreId = genreId;
movie.movieGenre(...);
};
...
let moviesPage = 1;
let seriesPage = 1;
document.getElementById('load-more').addEventListener('click', () => {
if (document.querySelector('#movies.active-link')) {
...
if (selection.genreId !== undefined) {
getMovies(selection.genreId, moviesPage);
}
} else if (...)) {
...
}
});
Closure
A more elegant way for you to accomplish this is by using a closure, but for that I have to know your code structure a bit more. For now, global state like the above will work for you.
Longer Answer
Your concerns have not been separated. You are mixing up more than one concern in your objects.
For e.g. to load more movies, in your load-more listener, you call a function named getMovies. However, from within the .dropdown-menu listener, you call into a movie object's method via the getByGenre method.
Ideally, you want to keep your UI concerns (such as selecting elements by using a query selector or reading data from elements) separate from your actual business objects. So, a more extensible model would have been like below:
var movies = {
get: function(howMany) {
if (howMany === undefined) {
howMany = defaultNumberOfMoviesToGetPerCall;
}
if (movies.genreId !== undefined) {
// get only those movies of the selected genre
} else {
// get all kinds of movies
}
},
genreId : undefined,
defaultNumberOfMoviesToGetPerCall: 25
};
document.get...('.load-more').addEventListener('whatever', (e) => {
var moviesArray = movies.get();
// do UI things with the moviesArray
});
document.get...('.dropdown-menu').addEventListener('whatever', (e) => {
movies.genreId = e.target.dataset.genreId;
var moviesArray = movies.get();
// do UI things with the moviesArray
});

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)
}

Why would you ever call .call() on Observable functions?

I am a relative beginner in Angular, and I am struggling to understand some source I am reading from the ng-bootstrap project. The source code can be found here.
I am very confused by the code in ngOnInit:
ngOnInit(): void {
const inputValues$ = _do.call(this._valueChanges, value => {
this._userInput = value;
if (this.editable) {
this._onChange(value);
}
});
const results$ = letProto.call(inputValues$, this.ngbTypeahead);
const processedResults$ = _do.call(results$, () => {
if (!this.editable) {
this._onChange(undefined);
}
});
const userInput$ = switchMap.call(this._resubscribeTypeahead, () => processedResults$);
this._subscription = this._subscribeToUserInput(userInput$);
}
What is the point of calling .call(...) on these Observable functions? What kind of behaviour is this trying to achieve? Is this a normal pattern?
I've done a lot of reading/watching about Observables (no pun intended) as part of my Angular education but I have never come across anything like this. Any explanation would be appreciated
My personal opinion is that they were using this for RxJS prior 5.5 which introduced lettable operators. The same style is used internally by Angular. For example: https://github.com/angular/angular/blob/master/packages/router/src/router_preloader.ts#L91.
The reason for this is that by default they would have to patch the Observable class with rxjs/add/operators/XXX. The disadvantage of this is that some 3rd party library is modifying a global object that might unexpectedly cause problems somewhere else in your app. See https://github.com/ReactiveX/rxjs/blob/master/doc/lettable-operators.md#why.
You can see at the beginning of the file that they import each operator separately https://github.com/ng-bootstrap/ng-bootstrap/blob/master/src/typeahead/typeahead.ts#L22-L25.
So by using .call() they can use any operator and still avoid patching the Observable class.
To understand it, first you can have a look at the predefined JavaScript function method "call":
var person = {
firstName:"John",
lastName: "Doe",
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
var myObject = {
firstName:"Mary",
lastName: "Doe",
}
person.fullName.call(myObject); // Will return "Mary Doe"
The reason of calling "call" is to invoke a function in object "person" and pass the context to it "myObject".
Similarly, the reason of this calling "call" below:
const inputValues$ = _do.call(this._valueChanges, value => {
this._userInput = value;
if (this.editable) {
this._onChange(value);
}
});
is providing the context "this._valueChanges", but also provide the function to be called base on that context, that is the second parameter, the anonymous function
value => {
this._userInput = value;
if (this.editable) {
this._onChange(value);
}
}
In the example that you're using:
this._valueChanges is the Input Event Observerable
The _do.call is for doing some side affects whenever the event input happens, then it returns a mirrored Observable of the source Observable (the event observable)
UPDATED
Example code: https://plnkr.co/edit/dJNRNI?p=preview
About the do calling:
You can call it on an Observable like this:
const source = Rx.Observable.of(1,2,3,4,5);
const example = source
.do(val => console.log(`BEFORE MAP: ${val}`))
.map(val => val + 10)
.do(val => console.log(`AFTER MAP: ${val}`));
const subscribe = example.subscribe(val => console.log(val));
In this case you don't have to pass the first parameter as the context "Observable".
But when you call it from its own place like you said, you need to pass the first parameter as the "Observable" that you want to call on. That's the different.
as #Fan Cheung mentioned, if you don't want to call it from its own place, you can do it like:
const inputValues$=this._valueChanges.do(value=>{
this._userInput = value;
if (this.editable) {
this._onChange(value);
}
})
I suppose
const inputValues$ = _do.call(this._valueChanges, value => {
this._userInput = value;
if (this.editable) {
this._onChange(value);
}
});
is equivalent to
const inputValues$=this._valueChanges.do(value=>{
this._userInput = value;
if (this.editable) {
this._onChange(value);
}
})
In my opinion it's not an usual pattern(I think it is the same pattern but written in different fashion) for working with observable. _do() in the code is being used as standalone function take a callback as argument and required to be binded to the scope of the source Observable
https://github.com/ReactiveX/rxjs/blob/master/src/operator/do.ts

How to override javascript method and call from class?

Excuse the title but I'm not really sure what this is called (Maybe events?):
I have created a class that someone will use:
function cls_something()
{
this.notify('hello');
}
Now the person using my class creates a method called 'notify' (as instructed by me) in order to listen for notifications and then perform their own custom code using the param I pass:
var something = new cls_something();
something.notify = function(message)
{
console.log('The notification is ' + message);
}
How do I call this method from within the class to give him the notification message?
Fiddle
I'm trying to achieve something like this...
websocket = new WebSocket("ws://localhost:10000");
websocket.onopen = function(e)
{
console.log('you are connected');
}
websocket.onmessage = function(e)
{
console.log('omg wtf ffs, there was an error: ' + e.msg);
}
You can just call this.notify("Message"); You'd probably want to check to see if it's defined first, though.
EDIT 1:
Ok, so your problem here is that you're calling a function straight from the constructor, before it's defined. If it needs to be defined in the constructor, then pass the function as a parameter.
function cls_something(notifyFunction)
{
notifyFunction('hello');
}
EDIT 2:
Just so we're clear, you can have the user of your class define functions later, if you'd like. You just can't run them straight from the constructor, obviously. If you run them from the constructor, they need to be defined before hand.
Say your class was something like
function cls_something()
{
this.someFunctionThatIsRunLater = function() {
this.notify('hello');
}
}
Then your client can write
var something = new cls_something();
something.notify = function(message)
{
console.log('The notification is ' + message);
}
Then, when the client calls
something.someFunctionThatIsRunLater();
Notify will be called.

Categories