javascript method writing patterns - javascript

This is regarding javascript programming pattern. while working with the gulp, I came across 2 different type of function calling pattern and this is really confusing so someone clarifies Is both functions are doing the same job?
gulp.watch(path.join(conf.paths.src, '/app/**/*.js'),
function(event) {
if(event.type === 'changed') {
callAMethod();
} else {
callBMethod();
}
});
in above method, we can write if else condition
but in this pattern
gulp.watch(path.join(conf.paths.src, '/app/**/*.js'))
.on('change', callAMethod);
If yes then please suggest some links Where I can read about it and which is the better way to handle the errors? also, where do we write else part in the later method style?

They are both different.
The first one is a callback to the gulp.watch method and it gets all the events that the watcher produces
The second one does not provide a callback, instead it subscribes to one event (change) produced.
The watch method returns a Gaze object and to handle errors, subscribe to the error event:
watcher.on('error', function(error) {
// Handle error here
});
Gulp4 which is still in alpha stage uses chokidar. To watch for errors, it's exactly the same as the above:
watcher.on('error', error => log(`Watcher error: ${error}`))

These functions are different.
Gulp uses a utility named glob-watcher for handling file changes and the first one is a callback called by glob-watcher.
The second one is a raw event from Event Emitter (NodeJS Emitter or Chokidar) instance.
Some events from EventEmmiter propagate to glob-watcher callback - for example, "change", so it may look the same on the first look.
For handling errors, I recommend having a look at gulp-plumber plugin.

Related

How does Javascript match the parameters for the callback function in fs.watchFile()

I'm attempting to recreate fs.watchFile() for a project, but I'm a bit confused on a particular subject. The question is about how does this callback function's parameters curr and prev gets populated?
fs.watchFile('message.text', (curr, prev) => {
console.log(`the current mtime is: ${curr.mtime}`);
console.log(`the previous mtime was: ${prev.mtime}`);
});
I've checked the node directory and analyzed the definition of the watchFile() function, but have found that it returns a single instance of stat object only.
https://github.com/nodejs/node/blob/master/lib/fs.js
This answer will have a bunch of links to a bunch of code, which is not desirable in StackOverflow, but I think it's for the best in this case.
I think this is the code you're looking for. Comes from here, where the listener (your function) is hooked on to the event 'change' on the stat variable, which is a StatWatcher (which is defined in the first file I linked to.
The callback gets triggered when the 'change' event is emitted on the corresponding StatWatcher instance which is defined in lib/internal/fs/watchers.js. The StatWatcher is created in lib/fs#line 1349 as part of the watchFile() function. The underlying implementation of StatWatcher is written in native code.
As you want to roll your own implementation it may be helpful to also have a look at the inotify package which implements monitoring file system events on a Linux System. Note, each "OS" has its concept of "file change" events.

jQuery-Chains in an AngularJS $timeout

Am I mistaken or is AngularJS' $timeout function buggy when it comes to jQuery-Chains (in this case jsTree)?
An exception is raised
$.(...).jstree(...).on is not a function
This is my snippet:
$timout(function() {
$("#foo").jstree().on('select_node:jstree', onSelect)
});
When not chaining the .on() but having it in an extra line like
$("#foo").on('select_node:jstree', onSelect)
there is no exception beeing thrown and the onSelect works fine.
Any hint is much appreciated!
you must download jstree and include that your project
https://github.com/vakata/jstree/zipball/3.2.1
Overview
Include a jsTree theme
Setup a container
Include jsTree
Create an instance
Listen for events
Interact with your instances
$(selector).jstree() returns an instance of $.jstree.core, and not a jQuery wrapped object.
Thus, you cannot chain it with the .on() handler setter - problem is completely unrelated from Angular / timeout issues of course.

How are custom broadcast events implemented in JavaScript (or jQuery)?

I want to implement a custom event that can be "broadcast", rather than sent to specific targets. Only those elements that have registered themselves as listeners for such events will receive them.
What I have in mind would look as follows.
First, in various places of the code, there would be statements of the form
some_subscriber.on_signal( 'some_signal', some_handler );
I'm using the term signal as shorthand for "broadcast event". In the expression above, some_subscriber registers itself as a listener of one type (called 'some_signal') of such signals, by providing a handler for it.
Elsewhere in the code, there would be statements of the form
publisher.signal_types[ 'some_signal' ].broadcast( event_data );
When statements like these get executed, a new event is generated and "broadcast". By this I mean that the code that calls the broadcast method has no direct information about the listeners for the signal it is issuing.
I have implemented a sketch of this idea in this jsFiddle, mostly in order to illustrate what I described in words above1. (It's certainly not production-grade, and I'm not particularly confident that it could be made so.)
The key elements of this implementation are the following. First, publisher objects do not keep track of their subscribers, as can be seen in the implementation of a factory method for such a publisher, shown below:
function make_publisher ( signal_types ) {
// ...
var _
, signal = {}
, ping = function ( type ) {
signal[ type ].broadcast( ... );
}
;
signal_types.forEach( function ( type ) {
signal[ type ] = $.register_signal_type( type );
} );
return { signal_types: signal_types, ping: ping };
}
This publisher object exposes only two items: the types of signals it broadcasts (in signal_types), and a ping method. When its ping method is invoked, the publisher responds by broadcasting a signal:
signal[ type ].broadcast( ... )
The ultimate recipients of this broadcast are nowhere to be seen in this code.
Second, elsewhere in the code, subscribers register themselves as listeners of these broadcast signals, like so
$( some_selector ).on_signal( signal_type, some_handler );
Note: It is basically impossible to illustrate the rationale for this scheme using an example that is both small and realistic. The reason for this is that the strength of this scheme is that it supports very loose coupling between the publisher code and subscriber code, and this is a feature that is never necessary in a small example. On the contrary, in a small example, code that implements such loose coupling invariably comes across as unnecessarily complex. It is therefore important to keep in mind that this apparent excess complexity is an artifact of the context. Loose coupling is very useful in larger projects. In particular, loose coupling via a publisher/subscriber-type pattern is one of the essential features of MVC.
My question is: is there a better (or at least more standard) way to achieve this effect of "broadcasting" custom events?
(I'm interested in both jQuery-based answers as well as "pure JS" ones.)
1An earlier, ill-fated version of this post was met with almost universal incomprehension, and (of course) the all-too-typical down-voting. With one exception, all the comments I got challenged the very premises of the post, and one directly questioned my grasp of the basics of event-driven programming, etc. I'm hoping that by presenting a working example of what I mean at least it won't come across as utterly inconceivable as it did when I described it in words alone. Luckily, the one helpful comment I did get on that earlier post informed me of the function jQuery.Callbacks. This was indeed a useful tip; the sketch implementation mentioned in the post is based on jQuery.Callbacks.
All right.
So I think what you can do is use the native dispatchEvent and addEventListener methods and use document as the only element for both publishing and subscribing to those events. Something like:
var myCustomEvent = new Event('someEvent');
document.dispatchEvent(myCustomEvent);
...
document.addEventListener('someEvent', doSomething, false);
And to make cross-browser, you could:
var myCustomEvent = new Event('someEvent');
document.dispatchEvent(myCustomEvent);
...
if (document.addEventListener) {
document.addEventListener('someEvent', doSomething, false);
} else {
document.attachEvent('someEvent', doSomething);
}
You can read more on the subject here and here. Hope this helps.
My question is: is there a better (or at least more standard) way to
achieve this effect of "broadcasting" custom events?
No, there is not a more standard way of doing publish/subscribe in Javascript. It is not directly built into the language or the browser and there are no platform standards for it that I'm aware of.
You have several options (most of which you seem aware of) to put your own system together.
You could pick a specific object such as the document object or the window object or a new object you create and use jQuery's .on() and .trigger() with that object as a central clearing house to cobble together a publish/subscribe-like model. You could even hide the existence of that object from your actual use by just coding it into a few utility functions if you want.
Or, as you seem to already know, you could use the jQuery.Callbacks functionality. There's even publish/subscribe sample code in the jQuery doc.
Or, you can find a third party library that offers a somewhat traditional publish/subscribe model.
Or, you can build your own from scratch which really just involves keeping a list of callback functions that are associated with a specific event so when that event is triggered, you can call each callback function.
If you came here looking for the jQuery way of doing this, here you go:
Add the event broadcast/dispatch code:
Syntax:
$(<element-name>).trigger(<event-name>);.
Example:
$.ajax({
...
complete: function () {
// signal to registered listeners that event has occured
$(document).trigger("build_complete");
...
}
});
Register a listener for the event:
Syntax:
$(<element-name>).on(<event-name>, function() {...});
Example:
$(document).on("build_complete", function () {
NextTask.Init();
});
Note:
Doing it this way: $(document).build_complete(function() {...}); leads to an error: Uncaught TypeError: $(...).build_complete is not a function.
I know this has been marked as answered back in 2015 -- but a solution that is also elegant and simple could be to use Redux

How can I attach an event handler to the process's exit in a native Node.js module?

I'm working on implementing correct memory management for a native Node.js module. I've ran into the problem described in this question:
node.js native addon - destructor of wrapped class doesn't run
The suggested solution is to bind the destructors of native objects to process.on('exit'), however the answer does not contain how to do that in a native module.
I've taken a brief look at the libuv docs as well, but they didn't contain anything useful in this regard, either.
NOTE: I'm not particularly interested in getting the process object, but I tried it that way:
auto globalObj = NanGetCurrentContext()->Global();
auto processObj = ::v8::Handle<::v8::Object>::Cast(globalObj->Get(NanNew<String>("process")));
auto processOnFunc = ::v8::Handle<::v8::Function>::Cast(processObj->Get(NanNew<String>("on")));
Handle<Value> processOnExitArgv[2] = { NanNew<String>("exit"), NanNew<FunctionTemplate>(onProcessExit)->GetFunction() };
processOnFunc->Call(processObj, 2, processOnExitArgv);
The problem then is that I get this message when trying to delete my object:
Assertion `persistent().IsNearDeath()' failed.
I also tried to use std::atexit and got the same assertion error.
So far, the best I could do is collecting stray ObjectWrap instances in an std::set and cleaning up the wrapped objects, but because of the above error, I was unable to clean up the wrappers themselves.
So, how can I do this properly?
I was also getting the "Assertion persistent().IsNearDeath()' failed" message.
There is a node::AtExit() function that runs just before Node.js shuts down - the equivalent of process.on('exit').
Pass a callback function to node::AtExit from within your add-on's init function (or where ever is appropriate).
The function is documented here:
https://nodejs.org/api/addons.html#addons_atexit_hooks
For example:
NAN_MODULE_INIT(my_exports)
{
// other exported stuff here
node::AtExit(my_cleanup);
}
NODE_MODULE(my_module, my_exports) //add-on exports
//call C++ dtors:
void my_cleanup()
{
delete my_object_ptr; //call object dtor, or other stuff that needs to be cleaned up here
}

simultaneously firing and events and location.path

We have a situation where we are utilizing a combination of events and routing inside of angular to handle navigation and communication between modules. Unfortunately the technique doesn't seem to work for us:
Neither this
Events.identifierSearch.fireOnChange(symbol);
$location.path('/explore');
nor this
Events.identifierSearch.fireOnChange(symbol);
$location.path('/explore');
Is working. The event handlers don't seem to fire. However a less optimal solution that we tried to demonstrate our event handlers are properly connected seems to work:
$location.path('/explore');
$timeout(function(){
var symbol = $event.target.innerText;
Events.identifierSearch.fireOnChange(symbol);
}, 500);
Now that is not what we want to have in our production code. In reality the "symbol" will be a large group of nested objects, so passing them on the URL of a route isn't ideal. And rewriting the routing seems like too much of a pain, it handles segregating partial pages nicely.
An idea i had would be to break this into two parts. First fire the event AND handle the event in the controller that fired it. This would require me adding a source to the event - so no sweat:
var controllerName = "thisBlahController" ;
Events.identifierSearch.fireOnChange(controllerName, symbol);
then in the same controller, handle the event and fire the location change:
$scope.$on(Events.identifierSearch.onChange, function() {
var source = Events.identifierSearch.source
if(source === controllerName) {
$location.path('/explore');
}
}
Again - it is not ideal, because it uses the assumption that the event has been handled by all sources prior to the route changing.
First, it would be great to know what it is in the angular routing that is causing the defusing of the events?
Second, I would love an official solution to this problem, one that has been battle tested.
Third, failing a systematic solution, can would like to hear opinions on the two solutions I have proposed up thread.
Quick modification
If i rewrite the order using the timeout approach:
Events.identifierSearch.fireOnChange(symbol);
$timeout(function(){
$location.path('/explore');
}, 1000);
The functionality doesn't seem to work either. Leading to question four Does a controller for a partial page, that is not the current ng-view get their event plumbing hooked up?

Categories

Resources