Using the modified version of M below, m can handle mixtures of synchronous and asynchronous arguments. idP(a) has no effect if a is a promise. Otherwise, idP transforms a into a promise. To see this in action, click "Restart" (below).
var dF3x = () => {}; function M (x) { return function go (func){ if (func === dF3x) return x; else x = idP(x).then(v => func(v)); return go; }; }; const m = M(3);
In the demonstration below, "m" is given mixtures of simple functions and promises.
The asynchronous functions used above are in this list:
function wait(ms) { return new Promise(r => setTimeout(r, ms)); } async function squareP (x) { await wait(300) return x*x; } let pause = t => async x => { await wait(t) return x; } async function hello (x) { await wait(1000) A = "Hello " await wait(700) B = "World" await wait(700) A = 42 await wait(700) B = 42 return x; } let divPinverse = a => async b => { await wait (300) return a/b; } let addP = x => async y => { await wait(300) return parseInt(x,10) + parseInt(y,10); } let doubleP = async y => { await wait(600) return 2 * parseInt(y,10) } let multP = x => async y => { await wait(600) return x * y; } let divP = a => async b => { await wait (300) return b/a; } async function cubeP (x) { await wait(600) return x*x*x; }
Here's the restart code:
function restart () { A = "A" B = "B" C = "C" D = "D" m(() => 4)(addP(3)) (squareP) (v => v-7)(dF3x).then(v => (A = v)); m(v => v/42)(v => v + 5)(v=>v*7)(pause(600))(dF3x).then(v => (B = v)); m(addP(7))(Math.sqrt)(v => v*6)(hello)(dF3x).then(a => (C = a)); m(divP(14))(v => v * 3)(addP(5))(v=> v * 3)(dF3x).then(v => (D = v)); }