Passing a function and its parameters as a parameter to another - javascript

I've seen a few answers but its still a little unclear to me how to go about this.
I have a retry function, whose parameter of fn I'd like to call with the original parameters supplied to it:
function retry(fn, retries=3, err=null) {
if (!retries) {
return Promise.reject(err);
}
return fn().catch(err => {
return retry(fn, (retries - 1), err);
});
}
Is there a clean way to do this in JS?
In short, I'd like to do something like:
function a(b,c,d) { return Promise.resolve(b + c + d) }
retry(a, ...originalParams)

Besides what you've covered yourself, another way would be to wrap your function and it's arguments into a thunk. However, it's not exactly what you would like it to be.
function retry(fn, retries=3, err=null) {
if (!retries) {
return Promise.reject(err);
}
return fn().catch(err => {
return retry(fn, (retries - 1), err);
});
}
function toThunk(fn, ...args) {
// note that we return a new function which closes over
// the function and arguments here (e. g. creating closures)
return () => fn(...args);
}
function sumP(a, b, c) {
return Promise.resolve(a + b + c);
}
// ---
retry(toThunk(sumP, 1, 2, 3)).then(result => {
console.log(result);
});

Related

How to write a customised Javascript function

I have dozens of functions with try catch block to handle and log any error occurred.
function add(a, b) {
try {
return a + b;
} catch (error) {
log.error(error.message + ' in add');
}
}
As this try catch statements have same kind of code for each function mentioning error message and the function name in each log, I want some way to avoid writing try catch for each function and want it to be added automatically. My function should be like below one but should work like above one.
function add(a, b) {
return a + b;
}
How could it be possible?
You can wrap your functions up using closures.
For logging, you can try using Function.name, but for meaningful information this rules out arrow functions and otherwise anonymous functions. This could be solved by explicitly passing a name string to the wrap function, but...
There is of course no guarantee the returned function is used via an identifier related to the original name (whatever vs anError below).
const wrap = func => (...args) => {
try {
return func.apply(this, args);
} catch (e) {
console.error(`${e} in ${func.name}`);
}
};
const add = wrap((a, b) => a + b);
const fail = wrap(t => {
if (t)
throw new Error('foo');
});
const whatever = wrap(function anError () {
throw 'an error';
});
console.log(add(1, 2));
fail(false);
fail(true);
whatever();
Combined output:
3
Error: foo in
an error in anError
can you try with callback...
function add(a, b){
return a + b;
}
function substract(a, b){
return a - b;
}
function calc(a){
try{
const f = Array.prototype.shift.apply(arguments);
return f(...arguments);
}catch(e){
console.log(e.stack);
}
}
calc(substract, 1, 2);

Calling function through Apply vs direct calling from Currying functions

I'm trying to implement currying function:
function sum(a, b, c) {
console.log('SUM'+JSON.stringify(arguments))
return a + b + c;
}
var curry= function (func,...n) {
return function(...args2) {
//console.log('arg2s'+args2)
return func.apply(this,n.concat(args2));
};
}
curry(sum,1,2)(3) //SUM{"0":1,"1":2,"2":3}, O/P:6
Above gives correct output, but i am not getting the necessity to use apply.
So, if i change my function to below:
var curry= function (func,...n) {
return function(...args2) {
//console.log('arg2s'+args2)
return func(n.concat(args2));
};
}
curry(sum,1,2)(3) //SUM{"0":[1,2,3]} O/P:"1,2,3undefinedundefined"
I basically have two questions here:
Why is the implementation of curry not working when calling func directly?Why is the output such weird ?
2.How do i change my function in a way that i can call it as below and should return sum:
curry(1)(2)(3)/curry(1,2)(3)/curry(1,2,3) etc instead of the way i'm calling currently.
I could find some solutions on the web, but couldn't understand .
ex:
function curry(func) {
return function curriedFunc(...args) {
if (args.length >= func.length) {
return func.apply(this, args);
} else {
return function(...args1) {
return curriedFunc.apply(this, args.concat(args1));
}
}
};
}
Any help would be highly appreciated !!
Your func accepts three arguments: a, b, and c. When you do:
return func(n.concat(args2));
you're passing it one argument, an array. It's equivalent to:
const arr = n.concat(args2);
return func(arr);
Sounds like you'd want to spread the arguments into the call of func instead:
return func(...n, ...args2)
With spread syntax, each item from the iterable is put into a parameter. Eg, if the n array has one item, it gets set as the first argument passed to func, and if args2 has 2 items, the first gets set as the second argument passed, and the second gets set as the third argument passed.
function sum(a, b, c) {
console.log('SUM' + JSON.stringify(arguments))
return a + b + c;
}
var curry = function(func, ...n) {
return function(...args2) {
return func(...n, ...args2);
};
}
curry(sum, 1, 2)(3);
How do i change my function in a way that i can call it as below and should return sum: curry(1)(2)(3)/curry(1,2)(3)/curry(1,2,3) etc
Keep track of the total number of arguments passed in a closure created the first time the function is called. In the returned function, push all arguments to the array, and if the array's length is 3, return the sum, otherwise return the function again:
function sum(a, b, c) {
return a + b + c;
}
var curry = function(func, ...argsSoFar) {
const neededArgs = func.length;
const returnedFn = (...args) => {
argsSoFar.push(...args);
if (argsSoFar.length === neededArgs) {
return func(...argsSoFar);
} else {
return returnedFn;
}
};
return returnedFn;
}
console.log(
curry(sum, 1, 2)(3),
curry(sum)(1, 2)(3),
curry(sum)(1)(2, 3),
curry(sum)(1)(2)(3),
);

Jest doesn`t mock(set spy) on needed function

My test function reverseAdd call another function add that is defined in same module.
I need to test, if test function call another.
Module
function add(a, b) {
return a + b;
}
function reverseAdd(a, b) {
add(b, a);
}
module.exports = {
add,
reverseAdd
}
Test
const exp = require('./add');
describe('add', () => {
it('should add two numbers', () => {
expect(exp.add(1, 2)).toBe(3);
});
it('should add two numbers', () => {
exp.add = jest.fn();
exp.reverseAdd();
expect(exp.add).toHaveBeenCalledTimes(1);
});
});
Result
Expected mock function to have been called one time, but it was called zero
As I understand wraped function is another function, and it is not called in test function.
How can I wrap/spy the function add?
playground: https://repl.it/repls/WoodenElectricInstances
Thanks #ltamajs, I found solution.
Need to rewrite module to
function add(a, b) {
return a + b;
}
function reverseAdd(a, b) {
module.exports.add(b, a); <----- here changes
}
module.exports = {
add,
reverseAdd
}

Trying to replicate callBack hell

I have been trying to learn about callBack hell, and was trying to replicate and then change it into promises. Here is my code, its saying on execution cb is not a function
What i am missing here.
var t = addTwo(function(a, b) {
console.log(a * b);
divideTwo(function() {
console.log("arshita");
})
})
function addTwo(cb) {
cb(3, 4);
}
function divideTwo(cb1) {
}
addTwo();
You have an error in your code
var t = addTwo(function(a, b) {
console.log(a * b);
divideTwo(function() {
console.log("arshita");
})
})
function addTwo(cb) {
cb(3, 4);
}
function divideTwo(cb1) {
}
addTwo((a, b) => a + b); // <----- Here you passed nothing, though `addTwo`
// expected a callback. I wrote an example callback that sums `a` and `b`
Update
If you want to see what callback hell looks like, then have a look at this (a simple, only 3-level callback hell):
function init(msg, cb) {
alert(msg)
cb()
}
function running(msg, cb) {
alert(msg)
cb()
}
function finish(msg) {
alert(msg)
}
// The below code may not be considered as "callback hell" yet, but add few more iterations and it definitely will become a hell
init('program started!', function() {
running('program is running', function() {
finish('program shut downs')
})
})

Anonymous callback functions

So, I understand callback functions to a degree. For instance, I completely understand this:
function finalGuy(x) {
alert("Final Number: " + x);
}
function secondGuy(x, callback) {
x = x - Math.sqrt(x);
callback(x);
}
function firstGuy(callback) {
var x = parseInt(prompt("Enter a number"));
x *= x;
secondGuy(x, callback);
}
firstGuy(finalGuy);
However, when faced with something like this I can't seem to grasp it.
a(function () {
b(function () {
c()
})
});
Can someone please translate the first sequence of callbacks into a working example like the second one? Specifically, passing one result to the next callback similarly to how I did it in the first example.
These two produce the same result
1.
function acceptCallback(callback) {
callback();
}
function callback() {
console.log('callback invoked');
}
acceptCallback(callback); // => 'callback invoked'
2.
function acceptCallback(callback) {
callback();
}
acceptCallback(function() {
console.log('callback invoked');
});
In the first example you pass a function declaration, in the second example you pass an anonymous function
3. Performing operations in the scope of a callback to be passed to another callback, aka "callback hell"
Nothing special here, it's the same syntax as the first two examples. This is difficult to read for anyone.
function first(callback) {
callback('from first');
}
function second(callback) {
callback('from second');
}
function third(callback) {
callback('from third');
}
function fourth(n, callback) {
callback(n * 10);
}
first(function(fromFirst) {
var a = 5;
console.log(fromFirst); // 'from first'
second(function(fromSecond) {
console.log(fromSecond); // 'from second'
third(function(fromThird) {
console.log(fromThird); // 'from third'
var b = a + 5; // 10
fourth(b, function(fromFouth) {
console.log(a, b, fromFourth); // 5, 10, 100
})
});
});
});

Categories

Resources