[comment]: # "markdown: { smartypants: true }" ## On Node.js ## Part 2: On Node.js
https://nodejs.org/en/about/resources/
# Prelude
If you don't have a _really_ good reason to use Rust ๐ฆ
... you should almost certainly be using Go. ๐น
### Why?
- Microsoft - C# (TS) [WikiPedia: TypeScript](https://en.wikipedia.org/wiki/TypeScript) - Yahuda Katz - Ruby (Ember) https://yehudakatz.com - CoffeeScript - Ruby - Elm - Erlang (Elixer) - JSX - OCaml (Reason) [React to the Future](https://www.youtube.com/watch?v=5fG_lyNuEAw) - Straight-up Ignorance - [TC-39 Proposal: RegExp.escape (comment)](https://github.com/tc39/proposal-regex-escaping/issues/37#issuecomment-1056902176)
!["node.js: too many cooks"](https://i.imgur.com/GIKXLBA.png)
> The Problem with React is JavaScript
- Creator of > React
(paraphrased)
React to the Future (2019)
https://youtube.com/watch?v=5fG_lyNuEAw?t=114
1:54 - 2:14
If you stand for nothing, You will fall for anything. ๐
!["classical learning curves"](https://i.imgur.com/RT2rUfV.png)
https://youtu.be/Uo3cL4nrGOk?t=323
I _do_ love JavaScript... but it's a minefield ๐ฃ
Y U No TypeScript!?!?
> When you mix two complex things together, you typically > get the multiplication of their demerits, not the sum of > their benefits (again, [WikiPedia: TypeScript](https://en.wikipedia.org/wiki/TypeScript))
# Node.js Gems
### 0. Install
Consistent, Conflict-free Install
- ~~brew~~ - ~~nvm~~ - ~~pkg~~ - ~~exe~~ - tar + webi
### 1. Less is More
JavaScript vs "The Good Parts"
vs ECMAScript
### 2. Classless
[beyondcodebootcamp.github.io/presos/classless-javascript](https://beyondcodebootcamp.github.io/presos/classless-javascript/)
Classless JavaScript (2021)
https://youtube.com/watch?v=-wz2Ued0Zkc
5:37 - 6:22
- "flat is better than nested" - [Zen of Python](https://github.com/ewjoachim/zen-of-python) - serializable as JSON - avoid shallow abstractions
Single, Package-level Export ```js var Person = module.exports; ```
Simple, this-less "constructor" ```js Person.create = function (p) { var person = { name: p.name || "Another Jane Doe", age: p.age || 0, }; // ... return person; }; ```
Package-level public methods ```js Person.save = async function (p) { return await request({ url: `/api/person/${p.id}`, json: p, }); }; ```
Private data via Closures ```js Person.create = function (p) { var person = { /* ... */ }; person.creditCard = function () { return "****-****-****-" + p.creditCard.slice(-4); }; // ... return person; }; ```
_"Composition over Inheritance"_ ```js function createApiRequester(baseUrl, key, secret) { return async function (url, data) { return await request({ url: `${baseUrl}/${url}`, auth: { user: key, pass: secret }, json: data, }); }; } ```
```js Person.api = createApiRequester( "https://example.co", "my-user", "my-token" ); await Person.api("/api/person/1"); await person.api("/api/person/1", { name: "AJ" }); ```
### 3. Array Methods
Don't
> Better to be absent of semantic meaning than to portray > the **wrong** semantic meaning.
> `reduce` is for **lossy** aggregation
```js [5, 4, 3, 2, 1].reduce(function (total, val) { return total + val; }); ```
the sum of the whole cannot be represented as its component parts
~~When in doubt~~ Always, `forEach()`.
```js var friendsMap = {}; friends.forEach(function (f) { friendsMap[f.id] = f; }); ```
### 4. โ Generics
Avoid useless abstractions
(particularly `lodash`, syntax sugar)
_"a little copying is better than a little dependency"_ ```js // โ leftpad(str, n, c); ``` ```js // โ String#padStart(n, c) ```
_"shallow abstractions do nothing in the fight against complexity"_ ```js // โ _.map(arry, fn); ``` ```js // โ arr.map(fn); ```
Explicit over implicit (low-context over high-context) ```js // โ [...arr]; ``` ```js // โ arr.slice(0); ```
```js // โ const foo = (x) => !x; ``` ```js // โ function foo(x) { return !x; } ```
Ternaries are the devil's playground ```js // โ let x = cond ? "special" : "default"; ``` ```js // โ "make the zero value useful" let x = "default"; if (cond) { x = "special"; } ```
No nesting templates ```js // โ (contrived, but you get the point) let greeting = `Hello, ${`${p.getTitle()} ${p.getName()}`}!`; ``` ```js // โ let title = p.getTitle(); let name = p.getName(); let greeting = `Hello, ${title} ${name}!`; ```
Stick to the built-in tooling
(unless you have a
very
good reason not to!)
- pnpm - yarn - ... ๐คฎ
**5. AJScript**
_"The Missing Pieces"_, on Speed Dial [github.com/coolaj86/AJScript/issues?q=label=std](https://github.com/coolaj86/AJScript/issues?q=label%3Astd)
- `Date._toLocalISOString()` - `Promise._sleep()` - `Promise._forEach()` - `Promise._map()` - `Math._randomInt()` - `RegExp._escape()`
(for top-level packages only: don't include in libraries)
### 6. Nothingness
- null - "not defined" - `undefined` - `delete` - `false` - `""` - `0`
```js // ๐คทโโ๏ธ person.spouse = null; // 'object' === typeof person.spouse ``` ```js // ๐คทโโ๏ธ person.spouse = undefined; ``` ```js // ๐คทโโ๏ธ delete person.spouse; ```
```js if ("spouse" in person) { // ... } ``` ```js if (person.spouse) { // ... } ``` ```js JSON.stringify(person); ```
```js if ("spouse" in person) { // ... } ``` ```js Object.keys(person); ``` ```js { ...person } ```
```js person.felon = person.felon ?? true; ``` ```js person.felon = person.felon || true; ```
### 7. const, let, var
The TRUTH about const, let, & var (2022)
https://youtube.com/watch?v=snrAnYQ9NXE
const: No such thing. ```js const person = { name: "AJ" }; person.name = "Mysterio"; ```
ALL CAPS, or bust ```js const PI = 3.141_592_653_589_793; ```
let go... ```js { let x = 11; { let x = 37; { let x = 42; } } { let x = 42; } } ```
let down... (temporal dead zone) ```js switch (x) { case 11: { let y = 11; } break; default: { let y = 11; } } ```
let me die... ```js foo: { bar: "baz"; } ```
`var`: Just Worksโข
### 8. await / catch
Don't trade one pyramid of doom for another... ```js // โ try { asyncable(); } catch (e) { // swallow error ?? } ``` ```js // โ await asyncable().catch(function (err) { // Correct or Classify, but do not Catch to silence... // (let errors bubble until they burst) }); ```
### 9. async router (proper error handling in express)
https://github.com/therootcompany/async-router
Async, Await, and Promises in Express for Node.js
https://youtube.com/watch?v=XFn0SJmGYs4
```js let server = express(); let app = new require("@root/async-router").Router(); app.get("/api/hello", async function (req, res) { // ... }); server.use(app); ```
Alternatively... ```js let server = express(); let app = express.Router(); app.get("/api/hello", function (req, res) { Promise.resolve() .then(async function (req, res) { // ... }) .catch(next); }); server.use(app); ```
Use the built-in error handler! ```js app.use("/", function (err, req, res, next) { if (isSafe(err)) { res.json(err); return; } console.error(err); res.statusCode = 500; res.json({ message: "internal error" }); }); ```
### 10. Buffers & Streams
Pipe, whenever possible. ```js input.pipe(output); ``` ```js let rs = Fs.createReadStream(fullpath); rs.name; // the file's name! rs.pipe(res); ```
Never use `data`! ```js rs.on("readable", function () { for (;;) { var chunk = rs.read(); if (!chunk) { break; } // ... } }); ```
## Porty Time! ๐ฅณ ๐ฝ