sandwich pattern in javascript code - javascript

Apologize if the title of the question is misleading. Actually I am looking for the javascript equivalent of the following python code:
## python code
def call_with_context(fn, *args):
## code to create context, e.g. profiling, db.connect, or drawing context store stack
fn(*args)
## code to close context
This implements the similiar functionality as the "with statement" in python, which implements the aspect-oriented paradigm.
So my question is what is the javascript way of doing such things? I have seen some code using Array.prototype.slice(arguments, 1) to do so, but I don't know if this is a common pattern in javascript, or there are better patterns supported in javascript (e.g. by closure) so ppl don't really do that. Pls also correct me if I am using the wrong keywords, because I really dont know how to refer to my problem with a better name than sandwich.
EDT 1: And I appreciate if someone can explain how to return the result of fn(*args) from inside the wrapper call_with_context. thanks!

I think a more typical JS way of doing this might be to decorate the function. So if you wanted to wrap your function in something that logged timing, you might create a function like this (off the top of my head):
var createTimer = function(fn) {
return function() {
var start = new Date();
var result = fn.apply(this, arguments);
console.log("Took " + (new Date() - start) + " ms.");
return result;
}
};
var test = function(a, b, c) {
return a * b + c;
}
test = createTimer(test);
console.log(test(3, 4, 5));
// Took 0 ms.
// 17
The main point is that you might not call something like this:
runTimerAround(test, 3, 4, 5);
although that could also be done in JS, it is, I believe less common than overwriting the functions directly.

It sounds like you want to call a method with specific context.
In js, you would typically do...
function someFunction( fn, context ) {
fn.call( context );
}
var Button = {
isClicked: false
};
someFunction(function () {
// this === Button
this.isClicked = true;
}, Button );
now the this keyword inside of fn will represent the context passed into the method someFunction. This sort of pattern is done quite often. Especially with the callbacks.

Here is my solution after some search. Hope it is helpful to others.
function call_with_context(fn) {
// some beginning code
console.log('begin');
r = fn.apply(null, Array.prototype.slice.call(arguments, 1));
// some ending code
console.log('end');
return r;
}

Something like this
// javascript code
function call_with_context(fn) {
// code to create context, e.g. profiling, db.connect, or drawing context store stack
var r = fn.call(Array.prototype.slice.call( arguments, 1)); // remove first arg - fn
//code to close context
return r;
}
so you will be able to do this:
call_with_context(myfun,1,2,3);
that will end up in call
myfun(1,2,3);

After having carefully read through every post/comment, I think the OP is
looking for [javascript] and [method-modification]. And answering right
away the OP's question about terminology, altering closed functionality in
JavaScript has nothing to do with Aspect-oriented Programming unless an
implementation that claims to be AO provides abstraction and code-reuse
levels for at least Aspect, Advice and Pointcut.
As it already has been commented
by Scott Sauyet, everything
else can be done by just (manually) wrapping functionality into one another. Here
again, I wouldn't go that far and calling it function-composition. In order to
qualify for that, there should be at least some tool-sets for it, as they already
exist with various implementations of compose and/or curry methods/patterns.
For what the OP is going to achieve there are a whole bunch of before, after
around / wrap solutions, mostly unfortunately mentioning AO(P), and in too
many cases not taking care of the context or target which is essential and
also has been ask for by the OP.
The example I do provide uses a prototypal implementation of Function.around.
Because JavaScript already features a standardized bind, I'm firmly convinced
that Function.prototype is the right place as well for some other method-modifiers
like before,
after,
around,
afterThrowing
and afterFinally.
code base that will support the afterwards following example:
(function (Function) {
var
isFunction = function (type) {
return (
(typeof type == "function")
&& (typeof type.call == "function")
&& (typeof type.apply == "function")
);
},
getSanitizedTarget = function (target) {
return ((target != null) && target) || null;
}
;
Function.prototype.around = function (handler, target) { // [around]
target = getSanitizedTarget(target);
var proceed = this;
return (isFunction(handler) && isFunction(proceed) && function () {
return handler.call(target, proceed, handler, arguments);
}) || proceed;
};
}(Function));
example code, altering a given closed function by additionally provided behavior before and after it and also providing it's context.
var loggingDelegate = function () { // closed code that can not be changed for any reason.
this.log.apply(this, arguments);
};
loggingDelegate.call(console, "log", "some", "arguments");
var interceptedLoggingDelegate = loggingDelegate.around(function (proceed, interceptor, args) {
// everything that needs to be done before proceeding with the intercepted functionality.
// [this] in this example refers to [console], the second argument of the [around] modifier.
this.log("proceed:", proceed); // the original functionality - here [loggingDelegate].
this.log("interceptor:", interceptor); // the modifying functionality - [around]s 1st argument.
this.log("args:", args); // the arguments that get passed around.
proceed.apply(this, args);
// or:
//return proceed.apply(this, args);
// or:
//var result = proceed.apply(this, args);
// everything that still needs to be done after invoking the intercepted functionality.
// if necessary:
//return result;
}, console); // [console] has to be provided as target to the modified [loggingDelegate].
interceptedLoggingDelegate("intercept", "and", "log", "some", "arguments");

Related

How setDefinitionFunctionWrapper() works in Cucumber JS?

I couldn't be able to find any good explanation of how the method works exactly and how it could be useable. In the documentation I found the description:
setDefinitionFunctionWrapper(fn, options)
Set a function used to wrap step / hook definitions. When used, the
result is wrapped again to ensure it has the same length of the
original step / hook definition. options is the step specific
wrapperOptions and may be undefined.
I'm not experienced programmer and I do not understand what "wrapping" means in this context. I'd be glad if someone will explain the subject more effectively
I tried using the snippet Jorge Chip posted and It does not work.
You should use this instead:
const {setDefinitionFunctionWrapper} = require('cucumber');
setDefinitionFunctionWrapper(function(fn){
if(condition){//you want to do before and after step stuff
return async function(){
//do before step stuff
await fn.apply(this, arguments)
//do after step stuff
}
}
else{//just want to run the step
return fn
}
}
in the snippet he posted he used args which will not work he also used await inside of a non async function which will also not work
A wrapper function is a subroutine in a software library or a computer program whose main purpose is to call a second subroutine or a system call with little or no additional computation.
Usually programmers wrap functions with another function to do extra small actions before or after the wrapped function.
myWrappedFunction () { doSomething }
myWrapper () { doSmallBits; myWrappedFunction(); doSmallBits; }
(1) https://en.wikipedia.org/wiki/Wrapper_function
Digging into CucumberJS, setDefinitionFunctionWrapper is a function that will be called on every step definition and should return the function you want to execute when that step is called.
An example of a dummy setDefinitionFunctionWrapper would be something like:
setDefinitionFunctionWrapper(function (fn, opts) {
return await fn.apply(this, args);
}
As of cucumber 2.3.1. https://github.com/cucumber/cucumber-js/blob/2.x/src/support_code_library/builder.js
After you install the cucumber library, see the source code in /node_modules/cucumber/lib/support_code_library/builder.js
At the line 95:
if (definitionFunctionWrapper) {
definitions.forEach(function (definition) {
var codeLength = definition.code.length;
var wrappedFn = definitionFunctionWrapper(definition.code, definition.options.wrapperOptions);
if (wrappedFn !== definition.code) {
definition.code = (0, _utilArity2.default)(codeLength, wrappedFn);
}
});
} else {
...
definitionFunctionWrapper bascially takes code(fn) and opts and return the new code(fn).
Understanding this piece of code we can make this function in our step file:
var { setDefinitionFunctionWrapper } = require('cucumber');
// Wrap around each step
setDefinitionFunctionWrapper(function (fn, opts) {
return function() {
console.log('print me in each step');
return fn.apply(this, arguments);
};
});

JS: Conventional structure for defining a callback function?

I've written a simple function which triggers a callback function once it is done printing out a certain string. Are there any caveats I should be aware of when structuring my callbacks the way I did?
Also, what would be the best approach if the original function were to be subjected to asynchronicity?
Code:
// Output via console
var message = "hello there";
function typeOut(message, callback = null, i = 0) {
var interval = setInterval(function() {
if (i < message.length) {
console.log(message.substring(0, i + 1));
i++;
} else {
clearInterval(interval);
callback();
}
}, 150);
//callback;
}
function postDialog() {
console.log('this is postdialog');
}
typeOut(message, postDialog);
Fiddle
Here
Two caveats:
Don't use null as a default value. This will inevitably throw an exception when called. Either use no default value, requiring the caller to provide a function, or use a function that does nothing (e.g. () => {}) for the default value.
The callback should always be the last parameter by convention. This makes calling a function with a long callback nicer, as all the arguments to the call are placed in the same spot, above the continuation.
Given that your i parameter is optional as well, this might not be trivial. Potential workarounds I can think of:
Don't make i a parameter at all - you're not using it anyway. Also in a real-world use case where you "animate" a DOM node it's trivial to prepend a constant prefix to the animated node.
Overload your function to have multiple signatures, and decide depending on the typeof the second parameter whether its i or callback. This does get tedious though.
And in general, the advise for writing new code in a modern code base is of course to use promises instead of callbacks! They will dispose of both the above problems:
function delay(ms) {
return new Promise(res => setTimeout(res, ms));
}
async function typeOut(message, i = 0) {
while (i < message.length) {
await delay(150);
i++;
console.log(message.slice(0, i));
}
}
var message = "hello there";
typeOut(message).then(function postDialog() {
console.log('this is postdialog');
});

More succinct delayed evaluation than function(){return x}?

I'm porting some Python code that relies heavily on delayed evaluation. This is accomplished by via thunks. More specifically, any Python expression <expr> for which delayed evaluation is desired gets enclosed within a Python "lambda expression", i.e. lambda:<expr>.
AFAIK, the closest JavaScript equivalent of this is function(){return <expr>}.
Since the code I'm working with is absolutely awash in such thunks, I'd like to make the code for them more succinct, if at all possible. The reason for this is not only to save characters (a non-negligible consideration when it comes to JS), but also to make the code more readable. To see what I mean, compare this standard JavaScript form:
function(){return fetchx()}
with
\fetchx()
In the first form, the substantive information, namely the expression fetchx(), is typographically obscured by the surrounding function(){return...}. In the second form1, just one (\) character is used as "delayed evaluation marker". I think this is the optimal approach2.
AFAICT, solutions to this problem would fall into the following categories:
Using eval to simulate delayed evaluation.
Some special JavaScript syntax that I don't know about, and that accomplishes what I want. (My vast ignorance of JavaScript makes this possibility look quite real to me.)
Writing the code in some non-standard JavaScript that gets programmatically processed into correct JavaScript. (Of course, this approach will not reduce the final code's footprint, but may at least retain some gains in readability.)
None of the above.
I'm particularly interested in hearing responses of the last three categories.
P.S.: I'm aware that the use of eval (option 1 above) is widely deprecated in the JS world, but, FWIW, below I give a toy illustration of this option.
The idea is to define a private wrapper class whose sole purpose would be to tag plain strings as JavaScript code for delayed evaluation. A factory method with a short name (e.g. C, for "CODE") is then used to reduce, e.g.,
function(){return fetchx()}
to
C('fetchx()')
First, definitions of the factory C and of the helper function maybe_eval:
var C = (function () {
function _delayed_eval(code) { this.code = code; }
_delayed_eval.prototype.val = function () { return eval(this.code) };
return function (code) { return new _delayed_eval(code) };
})();
var maybe_eval = (function () {
var _delayed_eval = C("").constructor;
return function (x) {
return x instanceof _delayed_eval ? x.val() : x;
}
})();
The following comparison between a get function and a lazyget function shows how the above would be used.
Both functions take three arguments: an object obj, a key key, and a default value, and they both should return obj[key] if key is present in obj, and otherwise, the default value.
The only difference between the two functions is that the default value for lazyget can be a thunk, and if so, it will get evaluated only if key is not in obj.
function get(obj, key, dflt) {
return obj.hasOwnProperty(key) ? obj[key] : dflt;
}
function lazyget(obj, key, lazydflt) {
return obj.hasOwnProperty(key) ? obj[key] : maybe_eval(lazydflt);
}
Too see these two functions in action, define:
function slow_foo() {
++slow_foo.times_called;
return "sorry for the wait!";
}
slow_foo.times_called = 0;
var someobj = {x: "quick!"};
Then, after evaluating the above, and using (e.g.) Firefox + Firebug, the following
console.log(slow_foo.times_called) // 0
console.log(get(someobj, "x", slow_foo())); // quick!
console.log(slow_foo.times_called) // 1
console.log(lazyget(someobj, "x",
C("slow_foo().toUpperCase()"))); // quick!
console.log(slow_foo.times_called) // 1
console.log(lazyget(someobj, "y",
C("slow_foo().toUpperCase()"))); // SORRY FOR THE WAIT!
console.log(slow_foo.times_called) // 2
console.log(lazyget(someobj, "y",
"slow_foo().toUpperCase()")); // slow_foo().toUpperCase()
console.log(slow_foo.times_called) // 2
prints out
0
quick!
1
quick!
1
SORRY FOR THE WAIT!
2
slow_foo().toUpperCase()
2
1...which may strike Haskell programmers as strangely familiar. :)
2There's another approach, the one used, e.g., by Mathematica, that avoids the need for delayed evaluation markers altogether. In this approach, as part of a function's definition, one can designate any one of its formal arguments for non-standard evaluation. Typographically, this approach is certainly maximally unobtrusive, but a bit too much so for my taste. Besides, it is not as flexible, IMHO, as using, e.g., \ as a delayed evaluation marker.
In my humble opinion I think you're looking at this problem from a wrong perspective. If you're creating thunks manually then you need to consider refactoring your code. In most cases thunks should be:
Either returned from lazy functions.
Or created by composing functions.
Returning Thunks from Lazy Functions
When I first started practicing functional programming in JavaScript I was mystified by the Y combinator. From what I had read online the Y combinator was a divine entity to be worshipped. It somehow allowed functions which didn't know their own name to call themselves. Hence it was the mathematical manifestation of recursion - one of the most important pillars of functional programming.
However understanding the Y combinator was no easy feat. Mike Vanier wrote that the knowledge of the Y combinator is a diving line between those people who are "functionally literate" and those who aren't. Honestly, the Y combinator in itself is dead simple to understand. However most articles online explain it backwards making it difficult to understand. For example Wikipedia defines the Y combinator as:
Y = λf.(λx.f (x x)) (λx.f (x x))
In JavaScript this would translate to:
function Y(f) {
return (function (x) {
return f(x(x));
}(function (x) {
return f(x(x));
}));
}
This definition of the Y combinator is unintuitive and it doesn't make apparent how the Y combinator is a manifestation of recursion. Not to mention that it cannot be used at all in eager languages like JavaScript because the expression x(x) is evaluated immediately resulting in an infinite loop which eventually results in a stack overflow. Hence in eager languages like JavaScript we use the Z combinator instead:
Z = λf.(λx.f (λv.((x x) v))) (λx.f (λv.((x x) v)))
The resulting code in JavaScript is even more confusing and unintuitive:
function Z(f) {
return (function (x) {
return f(function (v) {
return x(x)(v);
});
}(function (x) {
return f(function (v) {
return x(x)(v);
});
}));
}
Trivially we can see that the only difference between the Y combinator and the Z combinator is that the lazy expression x(x) is replaced by the eager expression function (v) { return x(x)(v); }. It is wrapped in a thunk. In JavaScript however it makes more sense to write the thunk as follows:
function () {
return x(x).apply(this, arguments);
}
Of course here we're assuming that x(x) evaluates to a function. In the case of the Y combinator this is indeed true. However if the thunk doesn't evaluate to a function then we simply return the expression.
One of the most epiphanous moments for me as a programmer was that the Y combinator is itself recursive. For example in Haskell you define Y combinator as follows:
y f = f (y f)
Because Haskell is a lazy language the y f in f (y f) is only evaluated when required and hence you don't run into an infinite loop. Internally Haskell creates a thunk for every expression. In JavaScript however you need to create a thunk explicitly:
function y(f) {
return function () {
return f(y(f)).apply(this, arguments);
};
}
Of course defining the Y combinator recursively is cheating: you are just explicitly recursing inside the Y combinator instead. Mathematically the Y combinator itself should be defined non-recursively to describe the structure of recursion. Nonetheless we all love it anyway. The important thing is that the Y combinator in JavaScript now returns a thunk (i.e. we defined it using lazy semantics).
To consolidate our understanding let's create another lazy function in JavaScript. Let's implement the repeat function from Haskell in JavaScript. In Haskell the repeat function is defined as follows:
repeat :: a -> [a]
repeat x = x : repeat x
As you can see repeat has no edge cases and it calls itself recursively. If Haskell weren't so lazy it would recurse forever. If JavaScript were lazy then we could implement repeat as follows:
function repeat(x) {
return [x, repeat(x)];
}
Unfortunately if executed the above code would recurse forever until it results in a stack overflow. To solve this problem we return a thunk instead:
function repeat(x) {
return function () {
return [x, repeat(x)];
};
}
Of course since the thunk doesn't evaluate to a function we need another way to treat a thunk and a normal value identically. Hence we create a function to evaluate a thunk as follows:
function evaluate(thunk) {
return typeof thunk === "function" ? thunk() : thunk;
}
The evaluate function can now be used to implement functions which can take either lazy or strict data structures as arguments. For example we can implement the take function from Haskell using evaluate. In Haskell take is defined as follows:
take :: Int -> [a] -> [a]
take 0 _ = []
take _ [] = []
take n (x:xs) = x : take (n - 1) xs
In JavaScript we would implement take using evaluate as follows:
function take(n, list) {
if (n) {
var xxs = evaluate(list);
return xxs.length ? [xxs[0], take(n - 1, xxs[1])] : [];
} else return [];
}
Now you can use repeat and take together as follows:
take(3, repeat('x'));
See the demo for yourself:
alert(JSON.stringify(take(3, repeat('x'))));
function take(n, list) {
if (n) {
var xxs = evaluate(list);
return xxs.length ? [xxs[0], take(n - 1, xxs[1])] : [];
} else return [];
}
function evaluate(thunk) {
return typeof thunk === "function" ? thunk() : thunk;
}
function repeat(x) {
return function () {
return [x, repeat(x)];
};
}
Lazy evaluation at work.
In my humble opinion most thunks should be those returned by lazy functions. You should never have to create a thunk manually. However every time you create a lazy function you still need to create a thunk inside it manually. This problem can be solved by lifting lazy functions as follows:
function lazy(f) {
return function () {
var g = f, self = this, args = arguments;
return function () {
var data = g.apply(self, args);
return typeof data === "function" ?
data.apply(this, arguments) : data;
};
};
}
Using the lazy function you can now define the Y combinator and repeat as follows:
var y = lazy(function (f) {
return f(y(f));
});
var repeat = lazy(function (x) {
return [x, repeat(x)];
});
This makes functional programming in JavaScript almost as fun as functional programming in Haskell or OCaml. See the updated demo:
var repeat = lazy(function (x) {
return [x, repeat(x)];
});
alert(JSON.stringify(take(3, repeat('x'))));
function take(n, list) {
if (n) {
var xxs = evaluate(list);
return xxs.length ? [xxs[0], take(n - 1, xxs[1])] : [];
} else return [];
}
function evaluate(thunk) {
return typeof thunk === "function" ? thunk() : thunk;
}
function lazy(f) {
return function () {
var g = f, self = this, args = arguments;
return function () {
var data = g.apply(self, args);
return typeof data === "function" ?
data.apply(this, arguments) : data;
};
};
}
Creating Thunks by Composing Functions
Sometimes you need to pass expressions to functions that are evaluated lazily. In such situations you need to create custom thunks. Hence we can't make use of the lazy function. In such cases you can use function composition as a viable alternative to manually creating thunks. Function composition is defined as follows in Haskell:
(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> f (g x)
In JavaScript this translates to:
function compose(f, g) {
return function (x) {
return f(g(x));
};
}
However it makes much more sense to write it as:
function compose(f, g) {
return function () {
return f(g.apply(this, arguments));
};
}
Function composition in mathematics reads from right-to-left. However evaluation in JavaScript is always from left-to-right. For example in the expression slow_foo().toUpperCase() the function slow_foo is executed first and then the method toUpperCase is called on its return value. Hence we want to compose functions in reverse order and chain them as follows:
Function.prototype.pipe = function (f) {
var g = this;
return function () {
return f(g.apply(this, arguments));
};
};
Using the pipe method we can now compose functions as follows:
var toUpperCase = "".toUpperCase;
slow_foo.pipe(toUpperCase);
The above code will be equivalent to the following thunk:
function () {
return toUpperCase(slow_foo.apply(this, arguments));
}
However there's a problem. The toUpperCase function is actually a method. Hence the value returned by slow_foo should set the this pointer of toUpperCase. In short we want to pipe the output of slow_foo into toUpperCase as follows:
function () {
return slow_foo.apply(this, arguments).toUpperCase();
}
The solution is actually very simple and we don't need to modify our pipe method at all:
var bind = Function.bind;
var call = Function.call;
var bindable = bind.bind(bind); // bindable(f) === f.bind
var callable = bindable(call); // callable(f) === f.call
Using the callable method we can now refactor our code as follows:
var toUpperCase = "".toUpperCase;
slow_foo.pipe(callable(toUpperCase));
Since callable(toUpperCase) is equivalent to toUpperCase.call our thunk is now:
function () {
return toUpperCase.call(slow_foo.apply(this, arguments));
}
This is exactly what we want. Hence our final code is as follows:
var bind = Function.bind;
var call = Function.call;
var bindable = bind.bind(bind); // bindable(f) === f.bind
var callable = bindable(call); // callable(f) === f.call
var someobj = {x: "Quick."};
slow_foo.times_called = 0;
Function.prototype.pipe = function (f) {
var g = this;
return function () {
return f(g.apply(this, arguments));
};
};
function lazyget(obj, key, lazydflt) {
return obj.hasOwnProperty(key) ? obj[key] : evaluate(lazydflt);
}
function slow_foo() {
slow_foo.times_called++;
return "Sorry for keeping you waiting.";
}
function evaluate(thunk) {
return typeof thunk === "function" ? thunk() : thunk;
}
Then we define the test case:
console.log(slow_foo.times_called);
console.log(lazyget(someobj, "x", slow_foo()));
console.log(slow_foo.times_called);
console.log(lazyget(someobj, "x", slow_foo.pipe(callable("".toUpperCase))));
console.log(slow_foo.times_called);
console.log(lazyget(someobj, "y", slow_foo.pipe(callable("".toUpperCase))));
console.log(slow_foo.times_called);
console.log(lazyget(someobj, "y", "slow_foo().toUpperCase()"));
console.log(slow_foo.times_called);
And the result is as expected:
0
Quick.
1
Quick.
1
SORRY FOR KEEPING YOU WAITING.
2
slow_foo().toUpperCase()
2
Hence as you can see for most cases you never need to create thunks manually. Either lift functions using the function lazy to make them return thunks or compose functions to create new thunks.
If you want delayed execution you should look in to using setTimeout.
setTimeout(function() {
console.log("I'm delayed");
}, 10);
console.log("I'm not delayed");
>I'm not delayed
>I'm delayed
https://developer.mozilla.org/en-US/docs/Web/API/window.setTimeout

How to execute a Javascript function only after multiple other functions have completed?

My specific problem is that I need to execute a (potentially) large number of Javascript functions to prepare something like a batch file (each function call adds some information to the same batch file) and then, after all those calls are completed, execute a final function to send the batch file (say, send it as an HTML response). I'm looking for a general Javascript programming pattern for this.
Generalize problem:
Given the Javascript functions funcA(), funcB(), and funcC(), I would to figure out the best way to order execution so that funcC is only executed after after funcA and funcB have executed. I know that I could use nested callback functions like this:
funcA = function() {
//Does funcA stuff
funcB();
}
funcB = function() {
//Does funcB stuff
funcC();
}
funcA();
I could even make this pattern a little more general by passing in callback parameters, however, this solution becomes quite verbose.
I am also familiar with Javascript function chaining where a solution might look like:
myObj = {}
myObj.answer = ""
myObj.funcA = function() {
//Do some work on this.answer
return this;
}
myObj.funcB = function() {
//Do some more work on this.answer
return this;
}
myObj.funcC = function() {
//Use the value of this.answer now that funcA and funcB have made their modifications
return this;
}
myObj.funcA().funcB().funcC();
While this solution seems a little cleaner to me, as you add more steps to the computation, the chain of function executions grows longer and longer.
For my specific problem, the order in which funcA, funcB, etc. are executed DOES NOT matter. So in my solutions above, I am technically doing more work than is required because I am placing all the functions in a serial ordering. All that matters to me is that funcC (some function for sending the result or firing off a request) is only called after funcA and funcB have ALL completed execution. Ideally, funcC could somehow listen for all the intermediate function calls to complete and THEN would execute? I hoping to learn a general Javascript pattern to solve such a problem.
Thanks for your help.
Another Idea:
Maybe pass a shared object to funcA and funcB and when they complete execution mark the shared object like sharedThing.funcA = "complete" or sharedThing.funcB = "complete" and then somehow? have funcC execute when the shared object reaches a state where all fields are marked complete. I'm not sure how exactly you could make funcC wait for this.
Edit:
I should note that I'm using server-side Javascript (Node.js) and I would like to learn a pattern to solve it just using plain old Javascript (without the use of jQuery or other libraries). Surely this problem is general enough that there is a clean pure-Javascript solution?
If you want to keep it simple, you can use a counter-based callbacks system. Here's a draft of a system that allows when(A, B).then(C) syntax. (when/then is actually just sugar, but then again the whole system arguably is.)
var when = function() {
var args = arguments; // the functions to execute first
return {
then: function(done) {
var counter = 0;
for(var i = 0; i < args.length; i++) {
// call each function with a function to call on done
args[i](function() {
counter++;
if(counter === args.length) { // all functions have notified they're done
done();
}
});
}
}
};
};
Usage:
when(
function(done) {
// do things
done();
},
function(done) {
// do things
setTimeout(done, 1000);
},
...
).then(function() {
// all are done
});
If you don't use any asynchronous functions and your script doesn't break the order of execution, then the most simple solution is, as stated by Pointy and others:
funcA();
funcB();
funcC();
However, since you're using node.js, I believe you're going to use asynchronous functions and want to execute funcC after a async IO request has finished, so you have to use some kind of counting mechanisms, for example:
var call_after_completion = function(callback){
this._callback = callback;
this._args = [].slice.call(arguments,1);
this._queue = {};
this._count = 0;
this._run = false;
}
call_after_completion.prototype.add_condition = function(str){
if(this._queue[str] !== undefined)
throw new TypeError("Identifier '"+str+"' used twice");
else if(typeof str !== "String" && str.toString === undefined)
throw new TypeError("Identifier has to be a string or needs a toString method");
this._queue[str] = 1;
this._count++;
return str;
}
call_after_completion.prototype.remove_condition = function(str){
if(this._queue[str] === undefined){
console.log("Removal of condition '"+str+"' has no effect");
return;
}
else if(typeof str !== "String" && str.toString === undefined)
throw new TypeError("Identifier has to be a string or needs a toString method");
delete this._queue[str];
if(--this._count === 0 && this._run === false){
this._run = true;
this._callback.apply(null,this._args);
}
}
You can simplify this object by ignoring the identifier str and just increasing/decreasing this._count, however this system could be useful for debugging.
In order to use call_after_completion you simply create a new call_after_completion with your desired function func as argument and add_conditions. func will only be called if all conditions have been removed.
Example:
var foo = function(){console.log("foo");}
var bar = new call_after_completion(foo);
var i;
bar.add_condition("foo:3-Second-Timer");
bar.add_condition("foo:additional function");
bar.add_condition("foo:for-loop-finished");
function additional_stuff(cond){
console.log("additional things");
cond.remove_condition("foo:additional function");
}
for(i = 0; i < 1000; ++i){
}
console.log("for loop finished");
bar.remove_condition("foo:for-loop-finished");
additional_stuff(bar);
setTimeout(function(){
console.log("3 second timeout");
bar.remove_condition("foo:3-Second-Timer");
},3000);
JSFiddle Demo
If you don't want to use any helper libraries, than you need to write some helper yourself, there's no simple one line solution for this.
If you'd like to end with something that looks as readable as it would in synchronous case, try some deferred/promise concept implementation (it's still plain JavaScript), e.g. using deferred package you may end up with something as simple as:
// Invoke one after another:
funcA()(funcB)(funcC);
// Invoke funcA and funcB simultaneously and afterwards funcC:
funcA()(funcB())(funcC);
// If want result of both funcA and funcB to be passed to funcC:
deferred(funcA(), funcB())(funcC);
Have a look into jQuery's deferred objects. This provides a sophisticated means of controlling what happens when in an asynchronous environment.
The obvious use-case for this is AJAX, but it is not restricted to this.
Resources:
jQuery docs: deferred object
good introduction to deferred object patterns
Non-AJAX use for jQuery's deferred objects
I was looking for the same kind of pattern. I am using APIs that interrogate multiple remote data sources. The APIs each require that I pass a callback function to them. This means that I cannot just fire off a set of my own functions and wait for them to return. Instead I need a solution that works with a set of callbacks that might be called in any order depending on how responsive the different data sources are.
I came up with the following solution. JS is way down the list of languages that I am most familiar with, so this may not be a very JS idiom.
function getCallbackCreator( number_of_data_callbacks, final_callback ) {
var all_data = {}
return function ( data_key ) {
return function( data_value ) {
all_data[data_key] = data_value;
if ( Object.keys(all_data).length == number_of_data_callbacks ) {
final_callback( all_data );
}
}
}
}
var getCallback = getCallbackCreator( 2, inflatePage );
myGoogleDataFetcher( getCallback( 'google' ) );
myCartoDataFetcher( getCallback( 'cartodb' ) );
Edit: The question was tagged with node.js but the OP said, "I'm looking for a general Javascript programming pattern for this," so I have posted this even though I am not using node.
Nowadays, one can do something like this:
Let's say we have both funcA, funcB and funcC:
If one's want funcA and funcB results to be passed to funcC:
var promiseA = new Promise((resolve, reject) => {
resolve(await funcA());
});
var promiseB = new Promise((resolve, reject) => {
resolve(await funcB());
});
var promise = Promise.all([ promiseA, promiseB ]).then(results => {
// results = [result from funcA, result from funcB]
return funcC(results);
});
If one's want funcA, then funcB and then funcC:
var promise = (
new Promise(async resolve => resolve( await funcA() ))
).then(result_a => funcB(result_a)).then(result_b => funcC(result_b));
And finally:
promise.then(result_c => console.log('done.'));
how about:
funcC(funcB(funcA)));
I think the questions is because some of functions run longer and there might be a situation when we run funcC when funcA or funcB did not fininsh executing.

Javascript code as a variable

Ok, this may sound a bit crazy but hear me out :)
I would like to do the following in javascript:
define START_OF_EVERY_FUNCTION = "try {"
define END_OF_EVERY_FUNCTION = "} catch () {}"
function TEST () {
START_OF_EVERY_FUNCTION
// rest of function
END_OF_EVERY_FUNCTION
}
Basically, can I define a list of javascript lines (code) and include them as above? I'm looking for a technique versus comments about whether this is a good idea or not or debate over wrapping all functions in a try/catch block.
I know about eval(), but I dont think you can eval statements like the above.
This might be goofy but you could define a master function and run other functions through it by passing them in.
var execute = function(func){
alert('before');
func();
alert('after');
};
function sayHi(){
alert('hi there');
}
execute(sayHi);
As requested, an example with passing arguments.
var execute = function(func){
alert('before');
var ret = func.apply(null, Array.prototype.slice.call(arguments, 1));
alert('after');
};
function saySomething(sayWhat){
alert(sayWhat);
}
execute(saySomething,'hey there');
That is not allowed in JavaScript.
You could extend the Function prototype:
Function.prototype.tryThis = function() {
try {
this();
}catch(ex){
alert('Caught '+ex);
};
};
function tryIt() {
alert('Inside tryIt');throw "My Error from tryIt";
}
tryIt.tryThis();
You need to look into aspect oriented programming for JavaScript. You can create hooks for function entry and exit. Tools like JSUnit do this for example.
I think you can do this with the "new Function" operator. I've never used it myself, since I'm not clinically insane, but I believe you can pass it a string which it will evaluate and use as the function body. You can also get the code for each function by calling myFunction.toString(). So put together, it'd be something like this:
var functionsToMessUp = ['myFunc1', 'myFunc2'];
for (var i = 0; i < functionsToMessUp.length; ++i) {
var theFunc = window[functionsToMessUp[i]]; // assuming they're in global scope
window[functionsToMessUp[i]] = new Function(
START_OF_EVERY_FUNCTION
+ theFunc.toString()
+ END_OF_EVERY_FUNCTION
);
}
Now, the above almost certainly won't work - there's parameters and other things to take into consideration, and I don't even think that's how the new Function constructor works, but if you really want to go down this path (which I really don't recommend), then this might be a good starting point for you.
Maybe something like this?
function tryCatch(callback) {
try {
callback();
} catch() {}
}
var myFunction = function() {
// do some stuff
};
tryCatch(myFunction);

Categories