[I'm a total newbie to Javascript so take it slow.]
I'm working on an app in node.js which will have a list of plugins. Each "plugin" should be a function (or 2) that can take a string and do something with it. The app should call each plugin in turn and pass it the string. Depending on the result it might call another function in that plugin etc...
What's the best way to design this in Javascript? I don't mind having to modify the app to add every plugin as its developed but would rather avoid having to do this a lot.
Right now I'm just thinking created a module for every module then "require" it within the primary app and call the function but that seems cludgy for a few reasons (a) I need to change the parent app quiet a bit for every new plugin, (b) there's no interface I can enforce on the plugins. I was kind of hoping there was some sort of contract I could force the plugins to respect.
You can list the plugin directory, and require each file. If each file adds a function to an existing object (say, myapp.plugins), you can just forEach the object and invoke each function. You can't really enforce a contract in the code without doing weird things like invoking an AST parser; you're better off doing unit testing on plugins to make sure they work in isolation.
EDIT:
Can you elaborate a bit on this part: "If each file adds a function to an existing object (say, myapp.plugins), you can just forEach the object and invoke each function."?
var invokePlugins = function() {
var args = arguments.slice(0);
myapp.plugins.forEach(function(plugin) {
plugin.apply(plugin, args);
});
}
invokePlugins("this", "gets", "passed to", "each plugin");
Your architecture is unclear, so this is just a very rough idea of what you could do.
Related
I have several functions that I'd like to replicate across different use cases in various requests and folders within the same collection (I'm using it as a template mostly, so it'll be pulling in variables externally)
There are many different suggestions in the Postman documentation but what's the best way to re-use code for such a use case?
What I've been doing lately is adding functions to my collection level pre-request script like so
collectionUtils = {
clearEnvData: function (pm) {
some useful code
},
// called after every request to ensure server coverage durring smoke testing.
cycleCurrentServer: function (serverCount, pm) {
some useful code
}
}
Then wherever I want to use these methods I do something like this
collectionUtils.cycleCurrentServer(index, pm);
I think generally the best way is to externalize the code into a library. You'll then make changes to the library and those changes will be reflected everywhere. Now there are several ways to implement this method, I'll leave with with the two that make sense for your use case:
Load your library from a remote site
If you are using some sort of development workflow that publishes your changes upstream, and you have your library published somewhere, you can load it at runtime:
pm.sendRequest("https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.0/dayjs.min.js", (err, res) => {
//convert the response to text and save it as an environment variable
pm.collectionVariables.set("dayjs_library", res.text());
// eval will evaluate the JavaScript code and initialize the min.js
eval(pm.collectionVariables.get("dayjs_library"));
// you can call methods in the cdn file using this keyword
let today = new Date();
console.log("today=", today);
console.log(this.dayjs(today).format())
})
Store your code on a collection variable and load it that way
A less pretty way to do it but more convenient to a lot of folks is just to drop the whole library into a collection variable like this:
Then you can load it when you need it:
const dayjs_code = pm.collectionVariables.get('dayjs_code');
// Invoke an anonymous function to get access to the dayjs library methods
(new Function(dayjs_code))();
let today = new Date();
console.log(dayjs(today).format())
In both cases when you update your library you either have to republish it or copy paste again to the collection variable. However that surely beats copy pasting a piece of code to 20 odd places and figuring out what's updated, what's not and fighting bugs while at it.
Edit: apparently it's not clear, guess I'll make it more concise.
Node application is built, uses a native addon. I need to pass in a Javascript function from this project through node-addon-api into my C++ addon. Then, I need to be able to call that function from C++ multiple times. The issue arose when I found out I am unable to save the reference to the Javascript function due to the napi_env (required for calling the function) being protected from caching.
Could not find any clear answers or examples on the internet regarding how to do this, looking for tips.
Original:
as the title describes, I need to figure out a way to call a JS function multiple times in my addon. Generic use case is that my addon does some long running commands and needs to periodically push a status update back to the javascript.
I thought the best approach would be to have the user pass in a function (which just appends to a text block) for my addon to call (so it can write the updates), this way the javascript side can decide where it gets displayed.
I have experimented to get this working. Found out that my original way of saving the function in a persistent napi_value doesn't work since you cannot save napi_env as well.
I found this thread, which I think is the closest to what I need, but I can't manage to translate the Nan to napi_ so it would work with what I'm using. Callback NodeJS Javascript function from multithreaded C++ addon
Also attempted passing in an EventEmitter, but similar problem as above.
Can anyone give some pointers on if I am heading in the right direction? Perhaps help me dig up a few examples on how to accomplish this?
Your question is not clear. Assuming you are using Javascript in Node, have a look at FFI which allows one to loading and calling dynamic libraries using Javascript.
Alternatively one can just execute a function as follows from the command line:
/usr/bin/node yourjsfunctionfilehere.js
You can also pass command line parameters to the called JS function.
Coming from a C# background, I used interfaces to base my mock objects off of. I created custom mock objects myself and created the mock implementation off a C# interface.
How do you do something like this in JS or node? Create an interface that you can "mock" off of and also the interface would serve for the real class that would also be able to implement that interface? Does this even make sense in JS or or the Node World?
For example in Java, same deal, define an interface with method stubs and use that as the basis to create real class or mock class off of.
Unfortunately you're not going to find the standard interface as a part of JavaScript. I've never used C#, but I've used Java, and correct me if I'm wrong, but it looks like you're talking about creating interfaces and overriding methods for both mock testing purposes, as well as being able to implement those interfaces in other classes.
Because this isn't a standard JavaScript feature, I think you'll find that there are going to be a lot of very broad answers here. However, to get an idea of how some popular libraries implement this, I might suggest looking at how AngularJS looks at mock testing (there are many resources online, just Google it. As a starting point, look at how they use the ngMock module with Karma and Jasmine.)
Also, because of JavaScript's very flexible nature, you'll find that you can override any sort of "class method" (that is, any function object that is a member of another object, whether that be a new'ed "class" or a plain object) by simply re-implementing it wherever you need to... there's no special syntax for it. To understand where and how you would accomplish this, I'd suggest looking from the ground up at how JavaScript using prototypal/prototypical inheritance. A starting point might be considering an example like this:
function Cat(config) {
if(typeof config !== 'undefined') {
this.meow = config.meow; // where config can possibly implement certain mock methods
}
}
Cat.prototype = {
this.meow = function() {
// the meow that you want to use as part of your "production" code
};
};
var config = {};
config.meow = function() {
// some mock "meow" stuff
};
var testCat = new Cat(config); // this one will use the mock "Cat#meow"
var realCat = new Cat(); // this one will use the prototype "Cat#meow"
In the above example, because of how JavaScript looks up the prototype chain, if it sees an implementation in the class itself, it'll stop there and use that method (thus, you've "overridden" the prototype method). However, in that example, if you don't pass in a config, then it'll look all the way up to the prototype for the Cat#meow method, and use that one.
TL;DR: there's not one good way to implement JavaScript interfaces, especially ones that double as mocks (there's not even a best way to implement dependency injection... that's also a foreign concept to JavaScript itself, even though many libraries do successfully implement it for cetain use-cases.)
I'm working on a very large javascript web app that doesn't really have a method to it. There seems to be an attempt to declare everything as part of a master object called "app". The original program existed as a single app.js file over 300k lines of code where the following was declared:
var app = {};
Beyond that everything in the app is written as such.
app.somefunction = function(args, callback) {
some code
};
This apparently allowed for the author to handily use Eclipse IDE "outline", which I confess I have started to enjoy having, never previously having been an IDE user I'm becoming a convert to the niceties they provide.
My question is, as I work on a phased refactor of this huge codebase, potentially trying to merge it into some sort of more established framework perhaps using something like require.js, is it OK to split the "app.js" up into smaller files and for the sake of sanity to be able to use the IDE outline declare app to be equal to itself in each one.
app = app;
I've tested this, it works from what I can tell and it allows the IDE to add all the subsequent functions to the outline window while making the project a little more manageable while I learn what it is actually doing. Are there any drawbacks to doing this? I imagine some async loading issues might occur; this could possibly add to client side overhead; or is this perfectly acceptable?
I realize that this is sort of a code philosophy question, but the simple Q&A would be, what effect would app=app; have?
There's no problem doing that.
In fact, this is pretty common code:
var app = app || {};
to initialize a variable only if it doesn't already have a value. In the case where it does already have a value, it will be exactly equivalent to your app = app;
This technique can also be useful for initializing a large object like you have in multiple chunks, allowing you to reorder and omit chunks at will, while being sure that no chunk is going to wipe another's initializations by doing var app = {}
I am looking for ways to build a system where I do not need to load all source files in order to play the application. My past project had over 200 .js files (I am not kidding!) and it was really slow to do a page reload to test features you develop.
I looked into Dojo and I see how they have built a dynamic loader. Basically you just load a single core component, then everything else will be loaded when needed.
I am thinking about implementing a factory method in my application that allows me to construct new instances of objects in JavaScript:
var user = MyApp.create('MyApp.model.User');
instead of:
var user = new MyApp.model.User();
The reasoning why I'd like to ditch the new keyword is because the former approach allows me to dynamically load the component in a lazy-loaded fashion if it does not exist already. The factory method can just look if the target object is defined, and if it is not, it would load it.
The only problem I am facing with that is the fact IDEs no longer understand user is type of MyApp.model.User which is certainly not a good thing.
Is there a way to solve this dilemma? Can I somehow JsDoc that factory method?
If your factory method returns various types of objects, based on the argument, then you can't document the return value for the factory method itself (using #returns) in a way that IDEs can make sense of. At least I'm not aware of any way to do it.
But you can solve your problem, easily, by annotating the variable which holds the object, like this:
/**
* #type {MyApp.model.User}
*/
var user = MyApp.create('MyApp.model.User');
Of course, I don't know if your particular IDE can interpret this. Mine can (using Komodo).