JS - Backend - CL2 Flashcards
Modules:
- importing own written modules
- algorhytm for modules searching (node_modules in the different levels)
UNDERSTANDING HOW NODE LOADS MODULES
In Node, modules are referenced either by fi le path or by name. A module that is referenced by a
name will eventually map into a fi le path unless the module is a core module. Node’s core modules
expose some Node core functions to the programmer, and they are preloaded when a Node process
starts.
Other modules include third-party modules that you installed using NPM (Node Package Manager)
or local modules that you or your colleagues have created.
Each module of any type exposes a public API that the programmer can use after the module is
imported into the current script. To use a module of any type, you have to use the require function
like this:
var module = require(‘module_name’);
This will import a core module or a module installed by NPM. The require function returns
an object that represents the JavaScript API exposed by the module. Depending on the module, that
object can be any JavaScript value — a function, an object with some properties that can be
functions, an array, or any other type of JavaScript object.
EXPORTING A MODULE The CommonJS module system is the only way you can share objects or functions among fi les in Node. For a suffi ciently complex application you should divide some of the classes, objects, or functions into reusable well-defi ned modules. To the module user, a module exposes exactly what you specify it to. The important bit here lies on the last line, where you defi ne what is to be exported by the module. module is a variable that represents the module you are currently in. module.exports is the object that the module will export to other scripts that require this module. You can export any object. In this case, you are just exporting the Circle constructor function, which a module user can use to create fully functional Circle instances.
Loading a Module As explained previously, you can use the require function to load a module. Having a require function call in your code does not change the state of the global namespaces, because there is no such thing in Node. If the module is found and doesn’t contain a syntax or initialization error, calling require() simply returns the module object, which you can then assign to any local variable you choose. There are several ways to reference modules, depending on which kind of module it is — a core module, a third-party module installed via NPM, or a local module. Let’s take a look at the different methods. Loading a Core Module Node has several modules compiled into its binary distribution. These are called the core modules, are referred to solely by the module name — not the path — and are preferentially loaded even if a third-party module exists with the same name. For instance, if you wanted to load and use the http core module, you would do the following: var http = require('http'); This returns the http module object that implements the API described in the Node API documentation.
Loading a File Module
You can also load a non-core module from the fi le system by providing the absolute path like this:
var myModule = require(‘/home/pedro/my_modules/my_module’);
Or you can provide a path relative to the current fi le:
var myModule = require(‘../my_modules/my_module’);
var myModule2 = require(‘./lib/my_module_2’);
Loading a Folder Module You can use the path for a folder to load a module like this: var myModule = require('./myModuleDir'); If you do so, Node will search inside that folder. Node will presume this folder is a package and will try to look for a package defi nition. That package defi nition should be a fi le named package.json . If that folder does not contain a package defi nition fi le named package.json , the package entry point will assume the default value of index.js, and Node will look, in this case, for a fi le under the path ./myModuleDir/index.js .
Loading from the node_modules Folder
If the module name is not relative and is not a core module, Node will try to fi nd it inside the
node_modules folder in the current directory.
For instance, if you do the following, Node will try to look for the fi le ./node_modules/myModule.js :
var myModule = require(‘myModule.js’);
If Node fails to fi nd the fi le, it will look inside the parent folder called ../node_modules/myModule
.js . If it fails again, it will try the parent folder and keep descending until it reaches the root or
fi nds the required module.
Caching Modules
Modules are cached the fi rst time they are loaded, which means that every call to
require(‘myModule’) returns exactly the same module if the module name resolves to the exact
same fi lename.
Events
https://www.sitepoint.com/nodejs-events-and-eventemitter/
Control flow (Async tasks, Callbacks): - Async await
https://stackabuse.com/node-js-async-await-in-es7/
Package.json:
- npm scripts
https: //blog.jayway.com/2014/03/28/running-scripts-with-npm/
https: //www.keithcirkel.co.uk/how-to-use-npm-as-a-build-tool/
Manipulating file paths
MANIPULATING FILE PATHS
File paths represent fi les, and these paths come in relative or absolute formats. You can concatenate
fi le paths, extract fi lename information, and even detect fi le existence.
In Node you can manipulate fi le paths by using strings, but that can become diffi cult, for instance,
when you want to join path components. For example, path components can be terminated with /,
but they don’t have to be, and accounting for those cases can be cumbersome. Path separators also
vary according to the OS.
Fortunately, Node has a module named path that enables you to normalize, join, and resolve paths,
as well as fi nd relative paths between absolute paths, extract components from paths, and determine
the existence of paths. In general, the path module simply manipulates strings and does not interact
with the fi lesystem to validate the strings (with the exception of the path.exists() function).
Normalizing Paths
Normalizing paths before you store or use them is often a good idea. For example, fi le paths that were
input by users or are present in a confi guration fi le, as well as paths that are the result of joining two
or more paths, usually need to be normalized. To do so, you can use the normalize function present
in the path module to normalize a path string, thus taking care of .. , . , and // . For instance:
var path = require(‘path’);
path.normalize(‘/foo/bar//baz/asdf/quux/..’);
// => ‘/foo/bar/baz/asdf’
Joining Paths
By using path.join() , you can concatenate path strings. You can concatenate as many as you like,
passing all of them as consecutive arguments like so:
var path = require(‘path’);
path.join(‘/foo’, ‘bar’, ‘baz/asdf’, ‘quux’, ‘..’);
// => ‘/foo/bar/baz/asdf’
As you can see, path.join() also normalizes the path.
Resolving Paths
You can resolve a series of paths into a normalized absolute path by using path.resolve() . It
works like an iterative cd command for every argument, except that it also works on fi les and it’s
abstract — it does not tap into the underlying fi lesystem to try to see if the path exists; it simply
manipulates paths.
For instance:
var path = require(‘path’);
path.resolve(‘/foo/bar’, ‘./baz’);
// => /foo/bar/baz
path.resolve(‘/foo/bar’, ‘/tmp/file/’);
// => /tmp/file
If the resulting path is not absolute, path.resolve will prepend the current working directory to
the path, as in this example:
path.resolve(‘wwwroot’, ‘static_files/png/’, ‘../gif/image.gif’);
// if currently in /home/myself/node, it returns
// => /home/myself/node/wwwroot/static_files/gif/image.gif’
Finding the Relative Path Between Two Absolute Paths
By using path.relative() , you can also determine how to get from one absolute path to another
absolute path. For example:
var path = require(‘path’);
path.relative(‘/data/orandea/test/aaa’, ‘/data/orandea/impl/bbb’);
// => ../../impl/bbb
Extracting Components of a Path
If you have a fi le path such as /foo/bar/myfile.txt , you may need to retrieve the parent directory
contents (the contents of /foo/bar ) or read another fi le inside the same directory. For that you have
to obtain the directory part of the fi le path by using path.dirname(filePath) . For example:
var path = require(‘path’);
path.dirname(‘/foo/bar/baz/asdf/quux.txt’);
// => /foo/bar/baz/asdf
In some cases, you might want to extract the fi lename from the fi le path, which is the last portion of
a path. You can do this by using the path.basename function:
var path = require(‘path’);
path.basename(‘/foo/bar/baz/asdf/quux.html’)
// => quux.html
A fi le path can also include an extension, which is usually the string in the base name after and
including the last . character.
You can subtract the fi le extension from the result by passing in an optional second argument with
the expected extension, like this:
var path = require(‘path’);
path.basename(‘/foo/bar/baz/asdf/quux.html’, ‘.html’);
// => quux
Determining the Existence of a Path
All the path manipulations and extractions you have seen so far don’t touch the underlying fi lesystem.
However, you might at some point need to determine whether a given path exists. For example, you
might need to ensure that a directory or fi le does not already exist before you create it. You can do
that by using path.exists()
In Node v0.8 path.exists was replaced by fs.exists , with the exact
same semantics.
Reading and Writing Files:
- fs.write vs fs.writeFile
- fs.read vs fs.readFile
https: //nodejs.org/dist/latest-v6.x/docs/api/fs.html#fs_fs_read_fd_buffer_offset_length_position_callback
https: //nodejs.org/dist/latest-v6.x/docs/api/fs.html#fs_fs_readfile_file_options_callback
https: //nodejs.org/dist/latest-v6.x/docs/api/fs.html#fs_fs_write_fd_buffer_offset_length_position_callback
https: //nodejs.org/dist/latest-v6.x/docs/api/fs.html#fs_fs_writefile_file_data_options_callback
HTTP create server:
- incomingMessage class methods
- serverResponse class methods
- handling URL Parameters
https: //nodejs.org/dist/latest-v6.x/docs/api/http.html#http_class_http_incomingmessage
https: //nodejs.org/dist/latest-v6.x/docs/api/http.html#http_class_http_serverresponse
Process:
- reading Command-Line Arguments
https://alligator.io/nodejs/command-line-arguments-node-scripts/
Spawning a Child Process:
- spawn
- fork
- exec
https://dzone.com/articles/understanding-execfile-spawn-exec-and-fork-in-node
socket. io basic operations:
- include in application
- create connection
- using chanels
https://www.tutorialspoint.com/socket.io/socket.io_quick_guide.htm
Express:
- authenticating with Passport
https://www.jokecamp.com/tutorial-passportjs-authentication-in-nodejs/
Debugging modules and applications
Building functional software is not a trivial task. Dividing your application code into small
modules and testing each one thoroughly can help, but you’re still bound to fi nd problems. If
you fi nd yourself in a situation where you need to inspect the inner workings of your Node
application or module code, several tools can help. This chapter covers several of those
debugging tools — console.log , Node’s built-in debugger, and Node Inspector.
USING CONSOLE.LOG
Node has some global objects that you can use without requiring them explicitly. One of them
is the console object, which enables you to output formatted strings.
The simplest debugging tool at your disposal is console.log . This function call does two
things — it serializes and concatenates your objects into a string and outputs the result to the
standard output stream. You can use it to inspect objects like this:
var obj = {a: 1, b: 2};
console.log(obj);
This last snippet prints the following:
{ a: 1, b: 2 }
This simple example passes in an object that is translated into a literal string representation. You
can pass in any type of object, and console.log will inspect its properties and values.
NOTE Actually, console.log does not do any formatting. All the formatting
is done by the util.format function. Whatever arguments you pass in to
console.log are handed over to util.format , and the result is fl ushed to the
standard output stream. This means that any of these example calls to console
.log can be directly applied to util.format .
USING NODE’S BUILT-IN DEBUGGER
Using console.log to inspect variables can quickly become unmanageable, especially when the
problem you are trying to fi x is nontrivial. When addressing a problem that is hard to fi nd, you
would probably have to add many log instructions and your program output would become too
verbose. Worst of all, you would have to run your program and try to reproduce the problem every
time you introduce new logging instructions.
Fortunately, the JavaScript V8 Virtual Machine exports a debugging interface, which Node also
supports. If you need to halt execution to carefully inspect your app, you can use Node’s built-in
debugger. Even though it’s simple and basic, it can be just enough to help you debug your app
without having to install another tool.
You can see that the a variable was not incremented as you intended it to be. Your next step is to
start Node in debug mode so you can observe what is happening.
$ node debug my_app.js
This code snippet launches Node in debug mode and starts the debugger. This will start the app but
will break at the fi rst line of your main module.
USING NODE INSPECTOR
Another debugging tool you might fi nd helpful is Node Inspector. Instead of using a text-only
debugger, this one provides a graphical interface by bringing the full-fl edged Google Chrome
inspector to your Node app using a web browser.
You can install Node Inspector globally like this:
$ npm install -g node-inspector
Node Inspector runs as a daemon by default on port 8080. You can launch it like this:
$ node-inspector &
This sends the node-inspector process to the background.
Next you need to fi re up your app, by using the –debug or –debug-brk option on the Node
executable like this:
$ node –debug-brk my_app.js
The –debug-brk option makes your app break on the fi rst line, whereas the –debug option simply
enables debugging.
NOTE When debugging servers you should use –debug , and when debugging
other scripts you might want to break on the fi rst line by using –debug-brk .
Now you can open your browser and point it to http://localhost:8080 , and you should get
something like the screen shown in Figure 18-1.
Understanding the boomerang effect or callback hell
When Node is performing an asynchronous operation, the result of that operation is not
communicated back using the function return value. Instead, asynchronous programming
relies on callback functions that are usually passed in as arguments.
When you need to leave your process and do some I/O, most of the time you need to specify a
callback function that gets invoked when that operation is fi nished.
If your task involves a lot of I/O operations, organizing the fl ow of callback functions can
become diffi cult and may lead to a pattern that is sometimes called “callback soup” or the
“boomerang effect.”
UNDERSTANDING THE BOOMERANG EFFECT
The “boomerang effect” happens when a group of callbacks is executed in chain — when
one I/O operation completes, the next operation starts. The name “boomerang” derives from
the shape of your code when there are many nested callback functions. The increasing left
indentation and the return of that indentation makes a boomerang-like shape.