How to pass an argument to a method using javascript? - javascript

i want to pass an argument to a method named checkMessages. checkMessages method is called in two places one call it with 1 argument and the other calls it with 2 arguments.
below is the code,
const checkMessages = (messages, isActive) => {
cy.logout();
changeUser(someuser);
if (isActive) {
cy.getByTestId('toggle').click();
messages.forEach(message =>
cy.get('textarea[id="description"]').type(message)
);
}
messages.forEach(message =>
cy.getTableRow('Description', message)
);
}
checkMessages([
`some message ${item1.name}were added`,
`some message ${item2.name} were added`,
]); // one method call with one argument
checkMessages([
`some message ${item1.name}were added`,
], isActive=true); // second method call with two arguments
//error with this function call
Now the problem is when the checkMessages method is called with 2 arguments call it throws error "isActive is not defined"
how do i pass this argument to checkMessages method. how should the function call be with this argument.
could someone help me with this. thanks.

You are passing isActive = true in your example. the isActive is property is not defined in the calling scope, hence throwing an error while calling the checkMessages function.
you can fix it by call the function by just passing the boolean true.
checkMessages([
`some message ${item1.name}were added`,
], true);

Javascript does not have keyword arguments. So in your line
checkMessages([
`some message ${item1.name}were added`,
], isActive=true);
you are trying to specify isActive as a keyword. Eslint thinks that you are trying to access a variable called isActive, which does not exist in the scope of the function caller. However, the code should still work because the isActive=true part will assign isActive as a global variable here.
If you want to use a similar thing to keywords, you can create a function that takes an object and use destructing assignment, like this
const checkMessages = (messages, {isActive}) => {
// ...
};
and then you can call it like this
checkMessages('...', {isActive: true});
That will give you a similar effect, but it's still not technically the same thing as keyword arguments.

Related

Calling object functions in middleware

I have this code in my middleware:
const UserMiddleware = {
isNumber(n) { return !Number.isNaN(parseFloat(n)) && !Number.isNaN(n - 0); },
// eslint-disable-next-line consistent-return
validateSignUp(req, res, next) {
const allSignUpErrors = [];
console.log(this.isNumber(5));
if (this.isNumber(req.body.first_name)) {
allSignUpErrors.push('First name must be a text value');
}
if (allSignUpErrors.length !== 0) {
return res.status(400).json({
status: 400,
error: allSignUpErrors,
});
}
next();
},
I normally use 'this.' to call functions and variables in objects without problems. I suspect that the 'next()' function in the middleware is what is causing me to get the error below at the point of using 'this.' to call a function.
TypeError: Cannot read property 'isNumber' of undefined
I have tried using 'bind' to call the function but the 'undefined' error still occurs.
Is the 'next()' function the one breaking the normal functionality? Is there a way to correctly use 'this.' to call functions in middleware?
Change:
this.isNumber(...)
to:
UserMiddleware.isNumber(...)
The value of this inside a middleware function will not be your UserMiddleware object unless you specifically used .bind() or some similar technology when passing it as middleware.
For help with further options, show us the code where you're using validateSignUp().
For example, if you were doing:
app.use(UserMiddleware.validateSignUp);
Then, you could set the desired value for this by using .bind() like this:
app.use(UserMiddleware.validateSignUp.bind(userMiddleware));
Passing UserMiddleware.validateSignUp to a function immediately loses the association with the UserMiddleware object and the this value when that function gets called will be determined by how the caller calls the function and won't be the UserMiddleware object. Using .bind(UserMiddleware) forces the desired this value to be set. .bind() actually creates a wrapper function who's sole job is to reattach the desired this value and that wrapper function is what is passed as the middleware handler. The middleware infrastructure calls the wrapper function with the wrong this value and then the wrapper function calls your validateSignUp function with the desired value of this - probably using .apply().
For a look at how .bind() works, you can see a polyfill for it here on MDN. For more of a discussion of how the value of this is set, see Six ways of setting this.

Why arrow function is not passing arguments?

I'm using angular w/ rxjs to observe user events on the interface. However, I'm having this really simple problem with passing arguments to a method in an arrow function. Here is the problem:
This is not working: searchterm is not being passed to this.searchFacilities
ngOnInit() {
this.searchTerm$.subscribe(searchterm => this.searchFacilities);/**Not working here**/
}
searchFacilities(term: string){
console.log(term);
this.facilityservice.searchFacilities(term)
.subscribe(results => this.facilityList = results);
}
But this works:
this.searchTerm$.subscribe(searchterm => { this.searchFacilities(searchterm); })
Clearly, I have other solutions that are pretty painless, but I really want to understand why my first approach is not working. Thanks!
Because the parameter is not passed directly to your function.
Example from the doc:
Rx.Observable.range(0, 3).subscribe(function (x) { console.log(x) });
The same example with an arrow function:
Rx.Observable.range(0, 3).subscribe(x => console.log(x));
Small clarification. The doc says you need to pass a callback to subscribe() and that this callback will receive the value(s) emitted by the observable.
We could write it like this:
const myCallBack = (val) => console.log(val);
Observable.range(0, 3).subscribe(myCallBack);
In your case you already have a callback, this.searchFacilities.
This means you can simply write:
this.searchTerm$.subscribe(this.searchFacilities);
Just like you can rewrite my original example to:
// Now `console.log` is the callback!
Observable.range(0, 3).subscribe(console.log);
In other words, the problem is not "Why arrow function is not passing arguments". The problem is that you created an arrow function whose body IS your callback, instead of just using your callback directly.
The expanded version of your code would look like this:
const myCallBack = (searchterm) => {
return this.searchFacilities;
}
As you can see, searchFacilities is neither invoked nor does it receive the searchterm param.
You could have run into the same problem with a NON-ARROW function by writing the following code (although the syntax of arrow functions does make the mistake more likely and insidious):
const myCallBack = function(searchterm) {
return this.searchFacilities;
}
Because you're getting a reference to the searchTerm but you're not doing anything with it. You could just do this.searchTerm$.subscribe(this.searchFacilities) and the term will be passed into the function.
You searchFacilities function is declared in global scope, and then is called inside of ngOnInit as a callback and its context is not anymore global scope, now this points to ngOnInit element Object. In order to work inside ngOnInit object you need to bind it and then searchFacilities be method of ngOnInit and in this way its going to work.

How to specify a parameter that can be undefined in flowjs

I'm new to flowjs and do not yet understand how the typical use case of an undefined parameter should be modeled in flowjs.
function msg(message: string, callback: ?Function) {
// ...
if (_.isFunction(callback)) {
callback();
}
}
When checking the above function with flow, the following error message is shown:
Function cannot be called on possibly null value function call.
Function cannot be called on possibly undefined value
I do understand why the errors are shown but I'm not sure how to tell flowjs that this is intentional because the callback is only invoked when the parameter is not null or undefined?
Flow does not know that _.isFunction(callback) returns true only if callback is a function. All it knows is that it returns a boolean (if you have the interface file for underscore/lodash set up). You should do native JS checks instead, then Flow can refine the type of callback from ?Function to Function. Like this: if (typeof callback === 'function') { callback() }.
A simpler type check should work as well: if (callback) { callback() } because Flow knows that if callback is not falsey, it has to be a function.
See more at https://flowtype.org/docs/dynamic-type-tests.html

how does the callback in fs.readfile get called when using fs.readfile.bind(context,pathArgument)

How does the callback in fs.readfile get called when using fs.readfile.bind(context,pathArgument) like so. //understandable because my task function knows the name of the callback parameter
async.series([function(callback){
//operation done callback()},...],finalCallback(err,result));
BUT
//not understandable
async.series([fs.someOperation.bind(null,firstArgument),...],finalCallback(err,esult))
I believe I understand partial application;however, it would look something like this. function(callback){ fs.someOperation(firstArgument, ????)}(asyncCallbackFunc) and then I have no idea how the second argument is called...
Thx, in advance for helping me clear this up.
All bind does is set the context of the callback. It is still a regular callback like any other. Except, it is explicitly told what this will be. Looks like in your case, it is set to null.
The bind function on function object allows you to set the context i.e the value of this inside the function body as well as allow you to create a partial function in case you pass some arguments while calling bind.
For example:
function add(a,b) {
console.log(this);
return a+b;
}
var newAdd = add.bind("hello world", 10);
The newAdd will be one argument function which gets added to 10 and the result is returned. Also when newAdd is called the "hello world" will be logged in console.
Now when your code says fs.readFile.bind(null, path) it means that the return function will be of one argument which is the callback for readfile i.e the return function will be of form function(callback) { ... } which is exactly what is required to be passed to async.series
The main idea in the code you posted is to create a partial function that accepts only callback so that it can be passed to async.series the null argument doesn't play any role but you need to pass a context argument to call bind function, hence a null is passed as context arg.

Pass data to Socket.io callback

client.on('message', function(obj){});
This works fine, but I am trying to avoid nesting, so I take the callback function out like so:
client.on('message', doThis(obj));
function doThis(obj) {}
But this gives me an error saying obj is undefined.
How do I pass the message data to the callback function?
Thanks
client.on('message', doThis);
function doThis(obj) {}
f(doThis) is the correct syntax. f(doThis(arg)) is the wrong syntax.
The latter is calling doThis immediately with the argument arg (which doesn't exist yet).
That's why it says obj is undefined because your calling doThis immediatly.
What f(doThis) does is passes the function on instead of the return value of the function

Categories