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);
};
});
Related
As soon as I've found out about JavaScript => syntax I run through my whole code and replaced every function keyword with =>. I guess it felt, well, cool. But then I figured that it actually isn't. So I replaced every => back to function keyword, and I run across a strange error:
const $ = (id) => document.getElementById(id);
class Car {
constructor(id, name, color, price) {
this.id = id;
this.name = name;
this.color = color;
this.price = price;
}
body() {
return(`
<div id="${this.id}">
<img src="${this.id}Img.png">
</div>
`);
}
tooltip() {
return(`
<div id="tooltip">
<p>The ${this.name} we offer is painted ${this.color}, and the price would be ${this.price} USD</p>
</div>
`);
}
generate() {
$('root').insertAdjacentHTML('beforeend', this.body());
// Error occurred here:
$(this.id + 'Img').onclick = function() {
$(this.id).insertAdjacentHTML('beforeend', this.tooltip());
}
// However, arrow function does the trick:
$(this.id + 'Img').onclick = () => {
$(this.id).insertAdjacentHTML('beforeend', this.tooltip());
}
}
}
const mercedes = new Car('mercedes', 'Mercedes', 'blue', 15000);
mercedes.generate();
Now, if I call some function that belongs to the global Object (I guess that's how it's called), in this example, onclick, I have to bind Cars this to it as well? .bind(this), or => function. Is this the reason arrow function was invented? Because, this inside onclick function actually refers to that global Object, or something...
Another example would be the first line of code I provided. Should I use arrow functions for returning 1 line of code, or should I wrap it like:
function $(id) {
return document.getElementById(id);
}
and really use arrow functions when they are absolutely mandatory? I figured if it's just 1 line of code that returns something, and since arrow functions don't need {} and return keyword, it would be OK to use them in that case. For example:
function main() {
const mercedes = new Car('mercedes', 'Mercedes', 'blue', 15000);
mercedes.generate();
}
window.onload = () => main();
Another example where I found them to be kind of helpful, is with callbacks. NodeJS code can get pretty messy, so omitting the function keyword can make it cleaner. However, having a function keyword on the other hand can make a lot of nested callbacks less confusing...
// Shorter syntax:
socket.on('listenEvent', (data) => {
// do something with data
});
// Less confusing, but longer syntax:
socket.on('listenEvent', function(data) {
// do something with data
});
So, if I wanted my first example to work, i would have to do:
$(this.id + 'Img').onclick = function() {
$(this.id).insertAdjacentHTML('beforeend', this.tooltip());
}.bind(this);
So, looking at it again, if that is what arrow function translates to, doing something like
const $ = function(id) {
return document.getElementById(id);
}.bind(this);
Kind of makes no sense... At the very end, I know that this question mostly comes down to personal preference. Is the class example I provided the only place where anyone would absolutely need to use =>, or function with bind? So opinions aside, is my understanding of arrows OK, or am I missing a point?
Thanks!
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');
});
Although I usually enjoy the callback-soup that is Node.JS, I found that a certain part of my code needs to be run in a blocking manner because of an SQLite issue. (Yes, I know I could try and address the SQLite part, it actually makes more sense to ensure blocking.)
I like using the async module, and though I have a feeling that module has a feature which can be used here, I can't seem to find it. Or, maybe there is a better module out there. Anyway, without further ado:
func = function(callback) {
let i = 0;
arr.forEach(val => {
if (val.trim().length > 0) {
console.log(`Starting for user ${val}.`);
let mylc = new lcapp(val);
////// TODO this needs to be made sycnronous. /////
async.series({
getMyDetails: callback => getMyDetails(mylc, callback)
}, (err, results) => handleResults(err, results, mylc, callback));
/////////////
}
});
};
The section of code surrounded by //// I would like to block until the handleResults function returns. I understand it will require reprogramming the callback in handleResults, or maybe I need to write a parent function around func but I'd like to see if StackOverflow people have some good ideas.
You could turn it into a function that recursively calls itself when the handleResults callback is hit.
You can do this by following the example below.
fun()
function fun() {
console.time("fun")
var arr = [1, 2, 3, 4, 5]
var i = arr.length - 1;
doStuff(doStuffCallback)
function doStuffCallback() {
if (i > 0) {
i--
doStuff(doStuffCallback)
} else {
console.timeEnd("fun")
}
}
function doStuff(callback) {
setTimeout(function() {
logIt()
callback()
}, 25)
}
function logIt() {
console.log(arr[i])
}
}
// Output:
// 5
// 4
// 3
// 2
// 1
// fun: about 160ms
PS: I'm assuming you only need to be synchronous within this method and the loop therein. Other code might still be running elsewhere in your application while this runs.
Yes, I know I could try and address the SQLite part, it actually makes more sense to ensure blocking.
No it doesn't, because you can't. You need to resolve whatever issue you have with it being async because there is no way to turn asynchronous code into synchronous code.
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");
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.