This function is supposed to return an object, however, the construction used below is unfamiliar to me. How does this function work?
function expect(value) {
return {
toBe: exp => console.log(success)
}
}
This is a standard JavaScript function:
function(parameter1, parameter2) {
return returnVal;
}
But the object that is being returned looks like this:
{
toBe: exp => console.log(success)
}
Which is an object containing an ES6 arrow function, and can be alternatively expressed like so (a direct translation to an ES5 function):
{
toBe: function(exp) {
return console.log(success);
}
}
Read here for more information on ES6 arrow function notation.
I think it worth emphasizing that returns an object with a key that contains a function as a value. You can run it in the same way to run a method belonging to a class. Obliviously it fails because there is no success defined.
function expect(value) {
return {
toBe: exp => console.log(success)
}
}
let res = expect('value')
console.log(res)
res.toBe('test')
I would say that this is the intent of the code, imo this makes a lot of sense; the evaluation is done when toBe is invoked, this invokes console.log(which tests the condition, when is invoked and prints the result):
function expect(value) {
return {
toBe: exp => console.log(exp === value)
}
}
expect('value').toBe('value')
expect('notvalue').toBe('value')
Related
I have a question regarding curry function..
I know that if I have this simple curry function:
const greeting = (greet) => {
return (name) => {
return `${greet} ${name}`;
};
};
I can call greeting('Hello')('John') and it will return Hello John.
Is there a way to make it flexible say between 1 parameter and 2 parameters, ex: with
the above greeting function, is there a way for me to call greeting('Hello') and greeting('Hello')('John') and it will return Hello and Hello John respectively?
I know that I can do it with greeting('Hello')() and greeting('Hello')('John') but I was just trying to avoid breaking changes because I already have a greeting method and want to extend it using curry function, so I want it to also accept greeting('Hello') without the extra () at the end...
thanks
I can think of only one option that works by coercing the curried function into a string. This won't change the return value but it will allow you to get the result you want depending on context.
const greeting = greet => Object.defineProperties(
name => `${greet} ${name}`, // curried
{
toString: {
value: () => greet,
},
valueOf: {
value: () => greet
}
}
)
console.log(typeof greeting("Hello")) // function, not string
console.log(`${greeting("Hello")}`) // note the string context
console.log(`${greeting("Hello")("World")}`)
If you need the return value to actually toggle between a function and a string however, the answer is no.
In order for greeting("Hello")("John") to return a string, greeting("Hello") must return a function.
There is no way to tell within greeting() how the curried function is going to be called so you cannot detect whether or not to return a function or a string.
Think of it this way, greeting("Hello")("John") is just a short version of...
const fn = greeting("Hello")
// later or maybe never...
fn("John")
You simply don't know how, when or even if that curried function will be called.
Is there a way? Sure. But why? because won't that be "un-currying" it? And you will have to modify the function of-course.
You can always do something like this just get the output your asked for:
const greeting = (greet) => {
const split = greet.split(" ");
if(split.length > 1)
return `${split[0]} ${split[1]}`;
else return (name) => {
return `${greet} ${name}`;
};
};
If you use a helper function for currying, you can get a similar behavior automatically. For example, take the implementation at javascript.info/currying-partials
function curry(func) {
return function curried(...args) {
if (args.length >= func.length) {
return func.apply(this, args);
} else {
return function(...args2) {
return curried.apply(this, args.concat(args2));
}
}
};
}
You can define
const greeting = curry((greet, name) => `${greet} ${name}`)
and call
greeting("Hello", "John")
or
greeting("Hello")("John")
I'm relatively new to js so please forgive me if my wording isn't quite right. I've also created a jsfiddle to demonstrate the issue.
Overview
In the app I'm working on, I have a function with a jquery ajax call, like this:
function scenario1(ajaxCfg) {
return $.ajax(ajaxCfg)
}
I want to change this function, but without in any way changing the inputs or outputs (as this function is called hundreds of times in my application).
The change is to make a different ajax call, THEN make the call specified. I currently have it written like this:
function callDependency() { //example dependency
return $.ajax(depUri)
}
function scenario2(ajaxCfg) {
return callDependency().then(() => $.ajax(ajaxCfg))
}
Desired Result
I want these two returned objects to be identical:
let result1 = scenario1(exampleCall)
let result2 = scenario2(exampleCall)
More specifically, I want result2 to return the same type of object as result1.
Actual Result
result1 is (obviously) the result of the ajax call, which is a jqXHR object that implements the promise interface and resolves to the same value as result2, which is a standard promise.
Since result2 is not a jqXHR object, result2.error() is undefined, while result1.error() is defined.
I did attempt to mock up these methods (simply adding a .error function to the return result, for example), but unfortunately even when doing this, result1.done().error is defined while result2.done().error is undefined.
Wrapping (or unwrapping) it up
In a nutshell, I want to return the jqXHR result of the .then() lambda function in scenario2 as the result of the scenario2 function. In pseudocode, I want:
function scenario2(ajaxCfg) {
return callDependency().then(() => $.ajax(ajaxCfg)).unwrapThen()
} //return jqXHR
What about something like this? The approach is a little different, but in the end you can chain .done() etc. to the scenario2() function:
const exampleCall = { url: 'https://code.jquery.com/jquery-1.12.4.min.js'};
const depUri = { url: 'https://code.jquery.com/jquery-1.12.4.min.js'};
function callDependency() { //example dependency
return $.ajax(depUri).done(() => console.log('returned callDependancy'))
}
let obj = { //creating an object with the scenario2 as a method so that I can bind it with defer.promise()
scenario2: function(ajaxCfg) {
return $.ajax(ajaxCfg).done(() => console.log('returned senario2')) // Purposely NOT calling the exampleCall() function yet
}
}
defer = $.Deferred(); // Using some JQuery magic to be able to return a jqXHR
defer.promise(obj); // Set the object as a promise
defer.resolve(callDependency()); // Invoking the callDependency() by default on promise resolve
obj.done(() => {
obj.scenario2() // Resolving so the callDependency() function can be called
}).scenario2(exampleCall).done(() => { // Here you can invoke scenario2 and FINALLY chain whatever you want after everything has been called
console.log('Here I can chain whatever I want with .done\(\) or .fail\(\) etc.')
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
What I think is cool about this way of doing it is that you can just keep adding methods to the object that you created, and then all your secondary functions that are built on top of callDependency() can be in one place. Not only that, but you can reuse those same methods on top of other AJAX calls.
Read more about this here.
I hope this helps!
I feel like your life would be made a lot easier if you used async/await syntax. Just remember though that async functions return a promise. So you could instead write:
async function scenario2(ajaxCfg) {
let jqXhrResult;
try {
await callDependency();
jqXhrResult = {
jqXhr: $.ajax(ajaxCfg)
};
} catch() {
// Error handling goes here
}
return jqXhrResult;
}
I actually thought of a way easier way to do this.
You can do it by adding a method to the function constructor's prototype object. That way any created function can inherit that method and you can still use the .done() syntax. It's referred to as prototypal inheritance:
const exampleCall = { url: 'https://code.jquery.com/jquery-1.12.4.min.js'};
const depUri = { url: 'https://code.jquery.com/jquery-1.12.4.min.js'};
function callDependency() {
return $.ajax(depUri).done(() => console.log('returned callDependancy'))
}
Function.prototype.scenario2 = function(ajaxCfg, ...args) {
return this(...args).then(() => $.ajax(ajaxCfg))
}
callDependency.scenario2(exampleCall).done(data => {
console.log(data)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
function say(something) {
console.log(something);
}
function exec(func, arg) {
return func(arg);
}
exec(say, "Hi, there.");
Why does this code work? I feel like it shouldn't since what is in the second function should return
say(something) (arg) {
console.log(something) ;
}
It works as it does because when you write return func(arg);, the func(arg) bit executes the function. What is returned is then the result of executing func(arg).
However, you're right that say() doesn't actually return a value, it just logs to the console within that function. The output you're seeing is the result of that log command. If you logged the returned value instead you'd see undefined as the result.
But if you'd passed a different function to exec which did return a value, then you'd need the return in exec() for it to work properly.
P.S. I'm not sure if this is part of what you're asking, but the difference between that and when you wrote exec(say, "hi there"); is that in that code, say is a reference to the "say" function. At that moment it's treated like any other variable, just the same as if you passed in a number or a string, for example.
The difference is the (), which causes the function to be executed, rather than passed as a reference.
In the question you seem to imply that you'd expect the source code of the say() function to be displayed, but this is not what it does, and also is not possible anyway.
Function say returns undefined (default value if no return keyword is used), and therefore function exec also returns undefined.
Proof:
function say(something) {
console.log(something);
}
function exec(func, arg) {
var result = func(arg);
console.log(result);
return result;
}
var result2 = exec(say, "Hi, there.");
console.log(result2);
Maybe you are looking for a closure, where exec returns a function for getting arg for the first handed over function func.
function say(something) {
console.log(something);
}
function exec(func) {
return function (arg) {
return func(arg);
};
}
exec(say)("Hi, there.");
I'm trying to simplify a line of code I do use everytime:
if (we_need_to_exit) { op(); return; }
Do I have a chance to define a function, something like this:
function my_return (x) {
x.op();
x.return;
}
and use it like:
if (we_need_to_exit) { my_return(this); }
Is it possible to define such a function?
Edit
Best simple solution that fits in my case is the following:
if (we_need_to_exit) { return op(); }
no, once you call my_return, that return inside of my_return is to return from within my_return.
You can probably do what you want by:
if (we_need_to_exit) { return my_fn(this); }
and your my_fn will be:
function my_fn (x) {
x.op();
// return any value you want, or use "return;" or just omit it
}
Why this won't work:
function my_return (x) {
x.op();
x.return; //[1] [2]
}
//-----and use it like-------------------
if (we_need_to_exit) { my_return(this); //[3]}
It means creating a return property on x, it won't return.
replacing x.return; with return; will return from the function, not from outside of it's call (at [3], which is your objective).
'my_return(this)' "this" will be set to the object calling the function the "if statement" is in.
function x(){
console.log(this); //shows the global object (window, if run in a browser)
}
var y = {
fruit:"apple",
x:function(){
console.log(this); // shows the calling object
}
};
x();
y.x();
Ok I'm guessing I'm missing something really simple on this one.
Lets say I have multiple methods that repeat a lot of the same things like this:
public getDepartments(id: number): ng.IPromise<IDepartmentViewModel[]> {
this.common.loadStart();
return this.unitOfWork.teamRepository.getDepartmentsForTeam(id).then((response: IDepartmentViewModel[]) => {
this.common.loadComplete();
return response;
}).catch((error) => {
this.common.loadReset();
return error;
});
}
Tons of boilerplate for a single call to this.unitOfWork.teamRepository.getDepartmentsForTeam(id)
so I wanted to make a generic wrapper for the boilerplate such as:
private internalCall<T>(method: () => ng.IPromise<T>): ng.IPromise<T> {
this.common.loadStart();
return method().then((response: T) => {
this.common.loadComplete();
return response;
}).catch((error) => {
this.common.loadReset();
return error;
});
}
Which I could then call like:
public getDepartments(id: number): ng.IPromise<IDepartmentViewModel[]> {
return this.internalCall<IDepartmentViewModel[]>(this.unitOfWork.teamRepository.getDepartmentsForTeam(id));
But I get the following error:
Supplied parameters do not match any signature of call target:
Type '() => ng.IPromise<IDepartmentViewModel[]>' requires a call signature, but type 'ng.IPromise<IDepartmentViewModel[]>' lacks one.
What is the right way to pass my method into the other to call it with supplied parameters?
This is a common mistake: you cannot pass a method function as a regular function since it requires the instance for the class as context. The solution is to use a closure:
function foo( func: () => any ) {
}
class A {
method() : any {
}
}
var instanceOfA = new A;
// Error: you need a closure to preserve the reference to instanceOfA
foo( instanceOfA.method );
// Correct: the closure preserves the binding to instanceOfA
foo( () => instanceOfA.method() );
For a more complete example you can also see my snippet published here: http://www.snip2code.com/Snippet/28601/Typescript--passing-a-class-member-funct
I needed to wrap the call so it was wrapped in a closure like so:
public getDepartments(id: number): ng.IPromise<IDepartmentViewModel[]> {
return this.internalCall<IDepartmentViewModel[]>(
() => { return this.unitOfWork.teamRepository.getDepartmentsForTeam(id); } // Wrapping here too
);
Only for documentation - I got this error when I accidentally called the wrong (existing) function with wrong parameters. Had to look into the errorous line in the packaged file .tmp/bla/bla/bla.ts to see the error.
Try replacing your fat arrow in to normal function. This will resolve the issue.
() => ng.IPromise
to
function(){ng.IPromise .....}
In my case a simpler trick allowed me to dodge the error. The call (or trigger) of a function is due to it parentheses, so :
class MyClass {
foo: any;
firstMethod() {
this.foo = this.secondMethod;
this.foo();
}
secondMethod() {
}
}
In a more generic answer, the error "Supplied parameters do not match any signature of call target in wrapper method - Typescript" points out that you are calling a function with the wrong parameters.
example() receives two parameters per definition, but you are passing only one:
example('param1') // wrong
example('param1','param2') // OK!