Javascript function for handling multiple unknown callbacks - javascript

I have a scenario where I would like to send in 2 or more functions (as parameters) into a handler function, and have that handler function execute each passed function as a callback function for the preceding function.
Here is a general concept of the function I am trying to write:
function functionChain() {
// MAKE SURE WE HAVE AT LEAST 1 PARAMETER
if ( arguments.length < 1 ) { return; }
// for each parameter, call it (as a function)
for ( var i=0; i<arguments.length; i++) {
if ( typeof arguments[i] === 'function' ) {
call arguments[i];
}
}
}
// example
functionChain( function1, function2, function3 );
... so in the code above, each function will be called in succession.
Where I am getting stuck is how to treat each call as a callback when the previous function completes.
The way I would approach this is to have a variable (for simplicity, lets just say a global variable named functionChainComplete), and wait to launch the next function -- and of course, each function I call would set functionChainComplete to true. So, something like this:
// set global var for tracking
var functionChainComplete;
function functionChain() {
// MAKE SURE WE HAVE AT LEAST 1 PARAMETER
if ( arguments.length < 1 ) { return; }
// SET GLOBAL VAR TO FALSE
functionChainComplete = true;
// for each parameter, call it (as a function)
for ( var i=0; i<arguments.length; i++) {
if ( typeof arguments[i] === 'function' ) {
if ( functionChainComplete == true ) {
// call the next function and wait for true again
functionChainComplete = false;
call arguments[i];
} else {
// try again in 50 ms (maybe setTimeout)?
}
}
}
}
function1() {
// do something, and when done, reset functionChainComplete
functionChainComplete = true;
}
function2() {
// do something, and when done, reset functionChainComplete
functionChainComplete = true;
}
function3() {
// do something, and when done, reset functionChainComplete
functionChainComplete = true;
}
// example
functionChain( function1, function2, function3 );
As you can see, the code above does not address the callback piece, and I am not sure where to take it from here - I suspect some sort of recursive function? I am stuck.

Say you have some function, double, that takes an argument, x, and a callback, k
const double = (x, k) =>
k(x * 2)
double(2, console.log) // 4
double(3, console.log) // 6
Now say we want to run it 3 times in a row
const double = (x, k) =>
k(x * 2)
const tripleDouble = (x, k) =>
double(x, y =>
double(y, z =>
double(z, k)))
tripleDouble(2, console.log) // 16
tripleDouble(3, console.log) // 24
But of course we had to statically code each continuation (y => ..., and z => ...). How would we make this work with a variable amount (array) of functions?
const double = (x, k) =>
k(x * 2)
const composek = (...fs) => (x, k) =>
fs.reduce((acc, f) =>
k => acc(x => f(x, k)), k => k(x)) (k)
const foo = composek(double, double, double)
foo(2, console.log) // 16
foo(3, console.log) // 24
This is ripe for some abstraction tho, and introduces my favourite monad, the Continuation Monad.
const Cont = f => ({
runCont: f,
chain: g =>
Cont(k => f(x => g(x).runCont(k)))
})
Cont.of = x => Cont(k => k(x))
const composek = (...fs) => (x, k) =>
fs.reduce((acc,f) =>
acc.chain(x =>
Cont(k => f(x,k))), Cont.of(x)).runCont(k)
const double = (x, k) =>
k(x * 2)
const foo = composek(double, double, double)
foo(2, console.log) // 16
foo(3, console.log) // 24
If you have freedom to change the functions you're chaining, this cleans up a little bit more – here, double has 1 parameter and returns a Cont instead of taking a callback as a second argument
const Cont = f => ({
runCont: f,
chain: g =>
Cont(k => f(x => g(x).runCont(k)))
})
Cont.of = x => Cont(k => k(x))
// simplified
const composek = (...fs) => (x, k) =>
fs.reduce((acc,f) => acc.chain(f), Cont.of(x)).runCont(k)
// simplified
const double = x =>
Cont.of(x * 2)
const foo = composek(double, double, double)
foo(2, console.log) // 16
foo(3, console.log) // 24
Of course if double was actually asynchronous, it would work the same
// change double to be async; output stays the same
const double = x =>
Cont(k => setTimeout(k, 1000, x * 2))
const foo = composek(double, double, double)
foo(2, console.log) // 16
foo(3, console.log) // 24

Something like this? (See comments, but fairly self-explanatory.)
function functionChain() {
var args = arguments;
// MAKE SURE WE HAVE AT LEAST 1 PARAMETER
if ( args.length < 1 ) { return; }
// Start the process
var i = -1;
go();
function go() {
// Pre-increment so we start at 0
++i;
if (i < args.length) {
// We have a next function, do it and continue when we get the callback
args[i](go);
}
}
}
Example:
function functionChain() {
var args = arguments;
// MAKE SURE WE HAVE AT LEAST 1 PARAMETER
if ( args.length < 1 ) { return; }
// Start the process
var i = -1;
go();
function go() {
// Pre-increment so we start at 0
++i;
if (i < args.length) {
// We have a next function, do it and continue when we get the callback
args[i](go);
}
}
}
// Just some functions for an example:
function a(callback) {
console.log("a");
callback();
}
function b(callback) {
console.log("b");
callback();
}
// Note this one is async
function c(callback) {
setTimeout(function() {
console.log("c");
callback();
}, 100);
}
function d(callback) {
console.log("d");
callback();
}
functionChain(a, b, c, d);
That said, one of the reasons for promises is to allow composing possibly-async functions. If your functions returned promises, we'd use the reduce idiom:
function functionChain() {
// Assumes the functions return promises (or at least thenables)
Array.prototype.reduce.call(arguments, function(p, f) {
return p.then(f);
}, Promise.resolve());
}
function functionChain() {
Array.prototype.reduce.call(arguments, function(p, f) {
return p.then(f);
}, Promise.resolve());
}
// Just some functions for an example:
function a(callback) {
return new Promise(function(resolve) {
console.log("a");
resolve();
});
}
function b(callback) {
return new Promise(function(resolve) {
console.log("b");
resolve();
});
}
// Note this one has a delay
function c(callback) {
return new Promise(function(resolve) {
setTimeout(function() {
console.log("c");
resolve();
}, 100);
});
}
function d(callback) {
return new Promise(function(resolve) {
console.log("d");
resolve();
});
}
functionChain(a, b, c, d);

This could be done with nsynjs:
Wrap all slow functions with callbacks into nsynjs-aware wrappers (see wait()),
Put your logic into function as if it was synchronous (see synchronousCode()),
Run that function via nsynjs engine (see nsynjs.run())
<script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>
<script>
var wait = function (ctx, ms) {
setTimeout(function () {
console.log('firing timeout');
ctx.resume();
}, ms);
};
wait.nsynjsHasCallback = true;
function synchronousCode() {
function function1() {
console.log('in function1');
wait(nsynjsCtx,1000);
};
function function2() {
console.log('in function2');
wait(nsynjsCtx,1000);
};
function function3() {
console.log('in function3');
wait(nsynjsCtx,1000);
};
function functionChain() {
// MAKE SURE WE HAVE AT LEAST 1 PARAMETER
if ( arguments.length < 1 ) return;
for ( var i=0; i<arguments.length; i++) {
//console.log(i,arguments[i]);
if ( typeof arguments[i] === 'function' ) {
arguments[i]();
};
};
};
functionChain(function1,function2,function3);
}
nsynjs.run(synchronousCode,{},function(){
console.log("Synchronous Code done");
})
</script>
See https://github.com/amaksr/nsynjs/tree/master/examples for more examples.

Related

How to merge 2 serializable functions into 1 serializable function in JS?

As you know, there are certain cases (e.g., use in workers) when functions need to be serializable (and, at the other side, deserializable of course). I have such a case; a library function (i.e. I cannot change it) doSomething(serializableFunction) expects such a function from me. Also it expects that serializableFunction accepts 1 parameter x and gives x to it.
So far, this was not a problem for me; I had one function f(x) from another library that fulfilled my purposes (so I just called doSomething(f) so far). But now, I have a second serializable function g(x), also from a library, and I want the function I give to doSomething to execute either f or g, dependent on x. So I tried:
doSomething(function h(x) {
if (x < 5) return f(x);
else return g(x);
});
This would work well without serialization, but with it, an error is thrown of course because h is not serializable anymore: It calls f and g, which are no longer known at deserialization time!
So currently I'm doing:
doSomething(eval(`function h(x) {
const f = ${f.toString()};
const g = ${g.toString()};
if (x < 5) return f(x);
else return g(x);
}`));
This works, but it's a nightmare! So my question is: Is there any better approach to merge 2 serializable functions (like fand g) into 1 function that is also serializable? Note that I cannot change any of f, g, or doSomething, just h!
I think of a solution replacing eval with new Funciton.
Not the best, but a bit better.
Example below:
function f(a) {
console.log("f", a);
}
function g(b) {
console.log("f", b);
}
function doSomething(func) {
const y = 1;
func(y);
}
const funcBody = `return function () {
const f = ${f.toString()};
const g = ${g.toString()};
if (x < 5) return f(x);
else return g(x);
}()`;
const func = new Function("x", funcBody);
doSomething(func);
Or you can add some abstraction like below:
function f(a) {
console.log("f", a);
}
function g(b) {
console.log("f", b);
}
function doSomething(func) {
const y = 1;
func(y);
}
const getFuncArray = (name = "x") => [
name,
`return function () {
const f = ${f.toString()};
const g = ${g.toString()};
if (${name} < 5) return f(${name});
else return g(${name});
}()`,
];
const res = new Function(...getFuncArray());
doSomething(res);

Question of partialLeft and partialRight function

These partialLeft and partialRight functions are containing same things in body but it takes different return values.
Why did come this situation?
function partialLeft(f, ...outerArgs) {
return function(...innerArgs) { // Return this function
let args = [...outerArgs, ...innerArgs]; // Build the argument list
return f.apply(this, args); // Then invoke f with it
};
}
// The arguments to this function are passed on the right
function partialRight(f, ...outerArgs) {
return function(...innerArgs) { // Return this function
let args = [...innerArgs, ...outerArgs]; // Build the argument list
return f.apply(this, args); // Then invoke f with it
};
}
// The arguments to this function serve as a template. Undefined values
// in the argument list are filled in with values from the inner set.
function partial(f, ...outerArgs) {
return function(...innerArgs) {
let args = [...outerArgs]; // local copy of outerargs template
let innerIndex=0; // which inner arg is next
// Loop through the args, filling in undefined values from inner args
for(let i = 0; i < args.length; i++) {
if (args[i] === undefined) args[i] = innerArgs[innerIndex++];
}
// Now append any remaining inner arguments
args.push(...innerArgs.slice(innerIndex));
return f.apply(this, args);
};
}
// Here is a function with three arguments
const f = function(x,y,z) { return x * (y - z); };
// Notice how these three partial applications differ
partialLeft(f, 2)(3,4) // => -2: Bind first argument:
2 * (3 - 4)
partialRight(f, 2)(3,4) // => 6: Bind last argument:
3 * (4 - 2)
partial(f, undefined, 2)(3,4) // => -6: Bind middle argument: 3 * (2 - 4)
these partialLeft and partialRight functions are containing same things in body
No they aren't. First does
let args = [...outerArgs, ...innerArgs];
Second does
let args = [...innerArgs, ...outerArgs];
so their order is reversed.

Multiple brackets function with rest parameter in JavaScript [duplicate]

I need a js sum function to work like this:
sum(1)(2) = 3
sum(1)(2)(3) = 6
sum(1)(2)(3)(4) = 10
etc.
I heard it can't be done. But heard that if adding + in front of sum can be done.
Like +sum(1)(2)(3)(4). Any ideas of how to do this?
Not sure if I understood what you want, but
function sum(n) {
var v = function(x) {
return sum(n + x);
};
v.valueOf = v.toString = function() {
return n;
};
return v;
}
console.log(+sum(1)(2)(3)(4));
JsFiddle
This is an example of using empty brackets in the last call as a close key (from my last interview):
sum(1)(4)(66)(35)(0)()
function sum(firstNumber) {
let accumulator = firstNumber;
return function adder(nextNumber) {
if (nextNumber === undefined) {
return accumulator;
}
accumulator += nextNumber;
return adder;
}
}
console.log(sum(1)(4)(66)(35)(0)());
I'm posting this revision as its own post since I apparently don't have enough reputation yet to just leave it as a comment. This is a revision of #Rafael 's excellent solution.
function sum (n) {
var v = x => sum (n + x);
v.valueOf = () => n;
return v;
}
console.log( +sum(1)(2)(3)(4) ); //10
I didn't see a reason to keep the v.toString bit, as it didn't seem necessary. If I erred in doing so, please let me know in the comments why v.toString is required (it passed my tests fine without it). Converted the rest of the anonymous functions to arrow functions for ease of reading.
New ES6 way and is concise.
You have to pass empty () at the end when you want to terminate the call and get the final value.
const sum= x => y => (y !== undefined) ? sum(x + y) : x;
call it like this -
sum(10)(30)(45)();
Here is a solution that uses ES6 and toString, similar to #Vemba
function add(a) {
let curry = (b) => {
a += b
return curry
}
curry.toString = () => a
return curry
}
console.log(add(1))
console.log(add(1)(2))
console.log(add(1)(2)(3))
console.log(add(1)(2)(3)(4))
Another slightly shorter approach:
const sum = a => b => b? sum(a + b) : a;
console.log(
sum(1)(2)(),
sum(3)(4)(5)()
);
Here's a solution with a generic variadic curry function in ES6 Javascript, with the caveat that a final () is needed to invoke the arguments:
const curry = (f) =>
(...args) => args.length? curry(f.bind(0, ...args)): f();
const sum = (...values) => values.reduce((total, current) => total + current, 0)
curry(sum)(2)(2)(1)() == 5 // true
Here's another one that doesn't need (), using valueOf as in #rafael's answer. I feel like using valueOf in this way (or perhaps at all) is very confusing to people reading your code, but each to their own.
The toString in that answer is unnecessary. Internally, when javascript performs a type coersion it always calls valueOf() before calling toString().
// invokes a function if it is used as a value
const autoInvoke = (f) => Object.assign(f, { valueOf: f } );
const curry = autoInvoke((f) =>
(...args) => args.length? autoInvoke(curry(f.bind(0, ...args))): f());
const sum = (...values) => values.reduce((total, current) => total + current, 0)
curry(sum)(2)(2)(1) + 0 == 5 // true
Try this
function sum (...args) {
return Object.assign(
sum.bind(null, ...args),
{ valueOf: () => args.reduce((a, c) => a + c, 0) }
)
}
console.log(+sum(1)(2)(3,2,1)(16))
Here you can see a medium post about carried functions with unlimited arguments
https://medium.com/#seenarowhani95/infinite-currying-in-javascript-38400827e581
Try this, this is more flexible to handle any type of input. You can pass any number of params and any number of paranthesis.
function add(...args) {
function b(...arg) {
if (arg.length > 0) {
return add(...[...arg, ...args]);
}
return [...args, ...arg].reduce((prev,next)=>prev + next);
}
b.toString = function() {
return [...args].reduce((prev,next)=>prev + next);
}
return b;
}
// Examples
console.log(add(1)(2)(3, 3)());
console.log(+add(1)(2)(3)); // 6
console.log(+add(1)(2, 3)(4)(5, 6, 7)); // 28
console.log(+add(2, 3, 4, 5)(1)()); // 15
Here's a more generic solution that would work for non-unary params as well:
const sum = function (...args) {
let total = args.reduce((acc, arg) => acc+arg, 0)
function add (...args2) {
if (args2.length) {
total = args2.reduce((acc, arg) => acc+arg, total)
return add
}
return total
}
return add
}
document.write( sum(1)(2)() , '<br/>') // with unary params
document.write( sum(1,2)() , '<br/>') // with binary params
document.write( sum(1)(2)(3)() , '<br/>') // with unary params
document.write( sum(1)(2,3)() , '<br/>') // with binary params
document.write( sum(1)(2)(3)(4)() , '<br/>') // with unary params
document.write( sum(1)(2,3,4)() , '<br/>') // with ternary params
ES6 way to solve the infinite currying. Here the function sum will return the sum of all the numbers passed in the params:
const sum = a => b => b ? sum(a + b) : a
sum(1)(2)(3)(4)(5)() // 15
function add(a) {
let curry = (b) => {
a += b
return curry;
}
curry[Symbol.toPrimitive] = (hint) => {
return a;
}
return curry
}
console.log(+add(1)(2)(3)(4)(5)); // 15
console.log(+add(6)(6)(6)); // 18
console.log(+add(7)(0)); // 7
console.log(+add(0)); // 0
Here is another functional way using an iterative process
const sum = (num, acc = 0) => {
if !(typeof num === 'number') return acc;
return x => sum(x, acc + num)
}
sum(1)(2)(3)()
and one-line
const sum = (num, acc = 0) => !(typeof num === 'number') ? acc : x => sum(x, acc + num)
sum(1)(2)(3)()
You can make use of the below function
function add(num){
add.sum || (add.sum = 0) // make sure add.sum exists if not assign it to 0
add.sum += num; // increment it
return add.toString = add.valueOf = function(){
var rtn = add.sum; // we save the value
return add.sum = 0, rtn // return it before we reset add.sum to 0
}, add; // return the function
}
Since functions are objects, we can add properties to it, which we are resetting when it's been accessed.
we can also use this easy way.
function sum(a) {
return function(b){
if(b) return sum(a+b);
return a;
}
}
console.log(sum(1)(2)(3)(4)(5)());
To make sum(1) callable as sum(1)(2), it must return a function.
The function can be either called or converted to a number with valueOf.
function sum(a) {
var sum = a;
function f(b) {
sum += b;
return f;
}
f.toString = function() { return sum }
return f
}
function sum(a){
let res = 0;
function getarrSum(arr){
return arr.reduce( (e, sum=0) => { sum += e ; return sum ;} )
}
function calculateSumPerArgument(arguments){
let res = 0;
if(arguments.length >0){
for ( let i = 0 ; i < arguments.length ; i++){
if(Array.isArray(arguments[i])){
res += getarrSum( arguments[i]);
}
else{
res += arguments[i];
}
}
}
return res;
}
res += calculateSumPerArgument(arguments);
return function f(b){
if(b == undefined){
return res;
}
else{
res += calculateSumPerArgument(arguments);
return f;
}
}
}
let add = (a) => {
let sum = a;
funct = function(b) {
sum += b;
return funct;
};
Object.defineProperty(funct, 'valueOf', {
value: function() {
return sum;
}
});
return funct;
};
console.log(+add(1)(2)(3))
After looking over some of the other solutions on here, I would like to provide my two solutions to this problem.
Currying two items using ES6:
const sum = x => y => (y !== undefined ) ? +x + +y : +x
sum(2)(2) // 4
Here we are specifying two parameters, if the second one doesnt exist we just return the first parameter.
For three or more items, it gets a bit trickier; here is my solution. For any additional parameters you can add them in as a third
const sum = x => (y=0) => (...z) => +x + +y + +z.reduce((prev,curr)=>prev+curr,0)
sum(2)()()//2
sum(2)(2)()//4
sum(2)(2)(2)//6
sum(2)(2)(2,2)//8
I hope this helped someone

Function that will execute function depending on value. Functional programming

I have two functions and they are executed depending of if statement. E.g.:
if(value) {
doA()
} else {
doB()
}
How to write function or object that will take the result and decide whether or not execute each function. I want to receive something like this:
exists(result).doA()
nothing(result).doB()
I want to learn some functional programming in JavaScrit so I woud appreciate any source from which I can learn FP in JavaScript.
continuation passing style
here's an approach using continuation passing style. you'll notice the implementation of main is not far off from your original encoding –
once you finish wrapping your head around this, if you haven't already learned about monads, you now know the best one (cont) ^_^
// cont :: a -> (a -> b) -> b
const cont = x =>
k => k (x)
// when :: (a -> boolean, a -> b, a -> b) -> a -> (a -> b) -> b
const when = (f,l,r) => x =>
f (x) ? cont (l (x)) : cont (r (x))
// isOdd :: number -> boolean
const isOdd = x =>
x & 1 === 1
// doA :: number -> number
const doA = x =>
x + 1
// doB :: number -> number
const doB = x =>
x * x
// main :: number -> void
const main = x =>
cont (x) (when (isOdd, doA, doB)) (console.log)
main (3) // IO: 4, doA (3) === 3 + 1
main (4) // IO: 16, doB (4) === 4 * 4
data constructors
here's another approach using simple data constructors Left and Right to represent a Fork sum type – this results in a sort of data-directed style where the control of main is determined by the input type
// type Fork a = Left a | Right a
// Left a :: { fork :: (a -> b, _) -> b }
const Left = x =>
({ type: Left, fork: (f,_) => f (x) })
// Right a :: { fork :: (_, a -> b) -> b }
const Right = x =>
({ type: Right, fork: (_,f) => f (x) })
// doA :: number -> number
const doA = x =>
x + 1
// doB :: number -> number
const doB = x =>
x * x
// main :: Fork a -> a
const main = f =>
// fork applies the left function (doA) to a Left
// fork applies the right function (doB) to a Right
f.fork (doA, doB)
console.log (main (Left (3))) // => 4, doA (3) === 3 + 1
console.log (main (Right (3))) // => 9, doB (3) === 3 * 3
You could write something like this, for example:
function exists(value) {
return function (func) {
if (value !== undefined) {
return func(value);
}
return null;
}
}
function nothing(value) {
return function (func) {
if (value === undefined) {
return func();
}
return null;
}
}
function doA(value) {
console.log('doing A', value);
}
function doB() {
console.log('doing B');
}
const foo = 'fool';
const bar = undefined;
exists(foo)(doA);
nothing(bar)(doB);
The exists function gets a value and returns another function. The function that is returned gets yet another function as argument, which is executed if the value passed is defined.
I've used “old school” anonymous functions in the example above to make it easier to understand. With ES6 arrow functions, you can write the exists and nothing functions more consisely, like this:
function exists(value) {
return func => value !== undefined ? func(value) : null;
}
function nothing(value) {
return func => value === undefined ? func(value) : null;
}
The “functional programming fun” really starts when you realize you can refactor these two functions by putting the common code in another function, that is then used to create the two functions, like this:
function executeWithCondition(predicate) {
return value => func => predicate(value) ? func(value) : null;
}
const exists = executeWithCondition(value => value !== undefined);
const nothing = executeWithCondition(value => value === undefined);
This technique is called currying.
Usage of these functions is still the same:
exists(foo)(doA);
nothing(bar)(doB);
Here's the complete runnable code example:
function executeWithCondition(predicate) {
return value => func => predicate(value) ? func(value) : null;
}
const exists = executeWithCondition(value => value !== undefined);
const nothing = executeWithCondition(value => value === undefined);
function doA(value) {
console.log('doing A', value);
}
function doB() {
console.log('doing B');
}
const foo = 'fool';
const bar = undefined;
exists(foo)(doA);
nothing(bar)(doB);
One approach would be to define the properties of an object with values set to functions
const o = {
exists: function(value) {
return value ? this.doA() : this.doB()
},
doA: function(value) {
console.log("A")
},
doB: function(value) {
console.log("B")
}
}
o.exists(void 0);

Recursion with Promises means registered callbacks get called many times

So my thinking was right, when recursing with promises, we end up calling all chained callbacks for however many times we recurse, for example
function p() {
return new Promise(function (r) {
process.nextTick(r);
})
}
function recurse(count) {
return p().then(function () {
if (count < 10) {
console.log('count => ', count);
return recurse(++count);
}
}).then(function(){
console.log('a');
return 5;
});
}
recurse(1).then(function () {
console.log('done');
});
If you run the above, we get:
count => 1
count => 2
count => 3
count => 4
count => 5
count => 6
count => 7
count => 8
count => 9
a
a
a
a
a
a
a
a
a
a
done
Is there a way to register this callback with console.log('a') just once instead of registering it 10 times?
I don't think I want/need this function to be called 10 times, and would like to find a way to have it called just once.
I am actually just as interested in a similar solution for Observables, specifically RxJS5 Observables.
I guess the only solution is to nest the remainder of your code inside the first promise callback like so:
function p() {
return new Promise(function (r) {
process.nextTick(r);
})
}
function recurse(count) {
return p().then(function () {
if (count < 10) {
return recurse(++count);
} else {
// all your remaining code would have to go here
console.log('a');
return 5; // or return someOtherPromise() or anything
}
});
}
recurse(1).then(function () {
console.log('done');
});
If the recursion is synchronous, you can simply recurse within the .then's function
new Promise(res => {
res(); // dummy initial promise
}).then(() => {
function recurse(x) { // recursion inside then
console.log('x', x);
if (x < 10) return recurse(++x);
return x;
}
return recurse(1); // begin recursion
}).then(y => { // this only fires once recursion above is resolved
console.log('y', y);
return 5;
}).then(z => console.log('z', z));
// x 1
// ... (synchronous)
// x 10
// y 10 (value passed from resolving inner promise)
// z 5 (value returned from previous then)
Or if our recursive function is asynchronous, we can have it return a promise too, so you end up with a recursion which looks like this
function doWork() {
function addOne(x) {
return new Promise((res, rej) => {
// async bit here
res(x + 1);
});
}
function recurse(x) {
if (x < 10) return addOne(x).then(recurse);
return x;
}
return recurse(1);
}
And in a promise chain, would look like this
new Promise(res => {
res(); // dummy initial promise
}).then(() => {
return doWork();
}).then(y => {
console.log(y);
});

Categories

Resources