The language all browsers converted to as of 2019, and therefore the easiest one to distribute and most widely implemented programming language.
Hopefully will be killed by WebAssembly one day.
Because JavaScript is a relatively crap/ad-hoc language, it ended up some decent tooling to make up for that, e.g. stuff like linting via ESLint and reformatting through Prettier is much more widespread than in other languages.
JavaScript data structure are also quite a bit anemic, which makes libraries such as lodash incredibly popular. But most of that stuff should be in the stdlib.
Our JavaScript examples can be found at:
  • Node.js example: examples that don't interact with any browser feature. We are just testing those on the CLI which is much more convenient.
  • JavaScript browser example: examples that interact with browser-specific features, notably the DOM
Likely the best JavaScript 2D game engine as of 2023.Uses Matter.js as a physics engine if enabled. There's also an alternative (in-house?) "arcade" engine: photonstorm.github.io/phaser3-docs/Phaser.Physics.Arcade.ArcadePhysics.html but it appears to be simpler/less robust (but also possibly faster).
TODO any 2D first person examples a bit like Ciro's 2D reinforcement learning games?
The examples are present under:
git clone https://github.com/photonstorm/phaser3-examples
but note that that repo is huge, about 4.5 GiB on local disk, as is has tons of assets.
The demos also include a Monaco-editor based sandbox mode where you can edit code directly on the web and see the game update which is a really sweet addition.
To run the demos locally, tested on Ubuntu 22.10:
git clone https://github.com/liabru/matter-js
cd matter-js
git checkout 0.19.0
npm install
npm run dev
and this opens up the demos on the browser.
Renderer questions:
A multi-scenario demo.
Node.js does have Node.js worker_threads however.
async is all present in JavaScript for two reasons:
God, it's impossible! You just have to convert the entire fucking call stack all the way up to async functions. It could mean refactoring hundreds of functions.
To be fair, there is a logic to this, if you put yourself within the crappiness of the JavaScript threading model. And Python is not that much better with its Global Interpreter Lock.
The problem is that async was introduced relatively late, previously we just had to use infinitely deep callback trees, which was worse:
myAsync().then(ret => myAsync2(ret).then(ret2 => myAsync3(re3)))
compared to the new infinitely more readable:
ret = await myAsync()
ret2 = await myAsync2(ret)
ret3 = await myAsync3(ret3)
But now we are in an endless period of transition between both worlds.
It is also worth mentioning that callbacks are still inescapable if you really want to fan out into a non-linear dependency graph, usually with Promise.all:
await Promise.all([
  myAsync(1).then(ret => myAsync2(ret)),
  myAsync(2).then(ret => myAsync2(ret)),
])
And then, after many many hours of this work, you might notice that the new code is way, way way slower than before, because making small functions async has a large performance impact: madelinemiller.dev/blog/javascript-promise-overhead/. Real world case with a 4x slowdown: github.com/ourbigbook/ourbigbook/tree/async-slow.
Anyways, since you Googled here, you might as well learn the standard pattern to convert callbacks functions into async functions using a promise: stackoverflow.com/questions/4708787/get-password-from-input-using-node-js/71868483#71868483
WellSync, if you are gonna useSync this wonky language thing inSync one place, you might as well useSync it everywhereSync and make it more decent. See also: how to convert async to sync in JavaScript.
This example counts to finity, sleeping 1 second between each count. Related:
In this section we will use the file nodejs/bench_mem.js, tests are run on Node.js v16.14.2 from NVM, Ubuntu 21.10, on Lenovo ThinkPad P51 (2017) which has 32 GB RAM.
A C hello world with an infinite loop at the end has:
  • 2.7 MB
  • 770 KB
For a Node.js infinite loop nodejs/infinite_loop.js
topp infinite_loop.js
This gives approximately:
  • RSS: 20 MB
  • VSZ: 230 MB
Adding a single hello world to it as in nodejs/infinite_hello.js and running:
topp infinite_hello.js
leads to:
  • RSS: 26 MB
  • VSZ: 580 MB
We understand that Node.js preallocates VSZ wildly. No big deal, but it does mean that VSZ is a useless measure for Node.js.
Forcing garbage collection as in nodejs/infinite_hello.js brings it down to 20 MB however:
topp node --expose-gc infinite_hello_gc.js
Finally let's see a baseline for process.memoryUsage nodejs/infinite_memoryusage.js:
node --expose-gc infinite_memoryusage.js
which gives initially:
{
  rss: 23851008,
  heapTotal: 6987776,
  heapUsed: 3674696,
  external: 285296,
  arrayBuffers: 10422
}
but after a few seconds randomly jumps to:
{
  rss: 26005504,
  heapTotal: 9084928,
  heapUsed: 3761240,
  external: 285296,
  arrayBuffers: 10422
}
so we understand that
  • heapUsed seems constant at 3.7 MB
  • heapTotal is a very noisy, as it starts at 7 MB, but randomly jumps to 9 MB at one point without apparent reason
Now let's run our main test program.
First a baseline case with an array of length 1:
node --expose-gc bench_mem.js n 1
This gives the same results as node --expose-gc infinite_memoryusage.js. The same result is obtained by doing:
a = undefined
with:
node --expose-gc bench_mem.js dealloc
Not let's vary the size of n a bit with:
node --expose-gc bench_mem.js n N
which gives:
NheapUsedheapTotalrssheapUsed per elemrss per elem
1 M14 MB48 MB56 MB1030
10 M122 MB157 MB176 MB1815
100 M906 MB940 MB960 MB99.3
"rss per elem" is calculated as: rss - 26 MB, where 26 MB is the baseline RSS seen on n 1.
Similarly "heapUsed per elem" deduces the 4 MB (approximation of the above 3.7 MB) seen on n 1.
Note that to reach MAX_SAFE_INTEGER we would need 8 bytes per elem worst case.
Everything below 100 million (8) is therefore very memory wasteful in terms of RSS.
If we use Int32Array typed array buffers instead of a simple Array:
node --expose-gc bench_mem.js array-buffer n N
we see that the memory is now, unsurprisingly, accounted for under arrayBuffers, e.g. for N 1 million:
{
  rss: 31776768,
  heapTotal: 6463488,
  heapUsed: 3674520,
  external: 4285296,
  arrayBuffers: 4010422
}
Results for different N:
|| N
|| `arrayBuffers`
|| `rss`
|| `rss` per elem

| 1 M
| 4 MB
| 31 MB
| 5

| 10 M
| 40 MB
| 67 MB
| 4.6

| 100 M
| 40 MB
| 427 MB
| 4
We see therefore that typed arrays are much closer to what they advertise (4 bytes per element), even for smaller element counts, as expected.
Now let's try one million objects of type { a: 1, b: -1 }:
node --expose-gc bench_mem.js obj
gives:
{
  rss: 138969088,
  heapTotal: 105246720,
  heapUsed: 70103896,
  external: 285296,
  arrayBuffers: 10422
}
Disaster! Memory usage is up to 70 MB! Why?? We were expecting only about 24, 4 baseline + 2 * 10 for each million int?!
And now an equivalent version using class:
node --expose-gc bench_mem.js class
gives the same result.
Let's try Array:
node --expose-gc bench_mem.js arr
is even worse at 78 MB!! OMG why.
{
  rss: 164597760,
  heapTotal: 129363968,
  heapUsed: 78117008,
  external: 285296,
  arrayBuffers: 10422
}
Let's change the number of fields on the object? First as a sanity check:
node --expose-gc bench_mem.js obj 2
produces as expected the smae result as:
node --expose-gc bench_mem.js obj
so adding properties one by one doesn't change anything from creating the literal all at once. Good.
Now:
node --expose-gc bench_mem.js obj N
gives heapUsed:
  • 1: 70M
  • 2: 70M
  • 3: 70M
  • 4: 70M
  • 5: 110M
  • 6: 110M
  • 7: 110M
  • 8: 134M
  • 9: 134M
  • 10: 134M
  • 11: 158M
Some usage examples under: Section "Sequelize example".
As of 2021, this library is extremely painful to use. It does feel semi-mature, but there are just too much horrible things going on;
Some glaring issues are listed at the horrors of Sequelize.
To run examples on a specific database:
  • ./index.js or ./index.js l: SQLite
  • ./index.js p: PostgreSQL. You must manually create a database called tmp and ensure that peer authentication works for it
All examples can be tested on all databases with:
cd sequelize
./test
Overview of the examples:
Exampes under nodejs/sequelize/raw:
This example is the same as nodejs/sequelize/raw/parallel_select_and_update.js, but going through Sequelize rather than with Sequelize raw queries. NONE is not supported for now to not have a transaction at all because lazy.
Sample invocation:
node --unhandled-rejections=strict ./parallel_select_and_update.js p 10 100 READ_COMMITTED UPDATE
where:
Other examples:
  • node --unhandled-rejections=strict ./parallel_select_and_update.js p 10 100 READ_COMMITTED UPDATE
Then, the outcome is exactly as described at: nodejs/sequelize/raw/parallel_select_and_update.js:
Transaction retries are inevitable, as some sQL isolation levels
This doesn't do a hole lot. Ciro Santilli wouldn't really call it a web framework. It's more like a middleware. Real web frameworks are built on top of it.
Examples under: nodejs/express:
  • nodejs/express/min.js: minimal example. Visit localhost:3000 and it shows hello world. It is a bit wrong because the headers say HTML but we return plaintext.
  • nodejs/express/index.js: example dump with automated tests where possible. The automated tests are run at startup after the server launches. Then the server keeps running so you can interact with it.
A live example on Heroku can be seen at: github.com/cirosantilli/heroku-node-min
gothinkster/realworld implementations based on Express.js.
Seemed to just work at 68bbadfd77f679f0df0fcd0de5bceb9c37b1144a Ubuntu 20.10, was forked from parent project in 2018.
Very raw. Easy to understand. Relatively well organiezd. But also very buggy at 3ab8d9f849a1cdf2985a8d123b1893f0fd4e79ab: github.com/Varun-Hegde/Conduit_NodeJS/issues/3, I just can't trust it. There must be several helper libraries that would greatly DRY up the repetitive CRUD. Ciro hates the style :-) 4 space indents, no space after commas, no semicolon. Not based on github.com/gothinkster/node-express-realworld-example-app which is essentially one of the reference implementations, so from scratch apparently, which is a bad sign.
Looks interesting.
It seems to abstract the part about the client messaging the backend, which focuses on being able to easily plug in a number of Front-end web framework to manage client state.
Has the "main web API is the same as the REST API" focus, which is fundamental 2020-nowadays.
Uses Socket.IO, which allows the client Javascript to register callbacks when data is updated to achieve Socket.IO, e.g. their default chat app does:
client.service('messages').on('created', addMessage);
so that message appear immediately as they are sent.
Their standard template from feathers generate app on @feathersjs/cli@4.5.0 includes:
  • several authentication methods, including OAuth
  • testing
  • backend database with one of several object-relational mapping! However, they don't abstract across them. E.g., the default Chat example uses NeDB, but a real app will likely use Sequelize, and a port is needed
which looks promising! They don't have a default template for a Front-end web framework however unfortunately: docs.feathersjs.com/guides/frameworks.html#the-feathers-chat lists a few chat app versions, which is their hello world:
But it is in itself a completely boring app with a single splash page, and no database interaction, so not a good showcase. The actual showcase app is feathersjs/feathers-chat.
And there is no official example of the chat app that is immediately deployable to Heroku: FeathersJS Heroku deployment, all setups require thinking.
Global source entry point: determine on package.json as usual, defaults to src/index.js.
The main FeathersJS hello world demo. Notable missing things...
The default feathers-chat app runs on NeDB (local filesystem JSON database).
Last updated 2018 as of 2021, but still just worked.
Also uses webpack which is fantastic.
Gotta run github.com/feathersjs/feathers-chat first: github.com/feathersjs-ecosystem/feathers-chat-react/issues/5, then it worked:
git clone https://github.com/feathersjs/feathers-chat
cd feathers-chat
git checkout fd729a47c57f9e6170cc1fa23cee0c84a004feb5
npm install
npm start
and on the other terminal:
git clone https://github.com/feathersjs-ecosystem/feathers-chat-react
cd feathers-chat-react
git checkout 36d56cbe80bbd5596f6a108b1de9db343b33dac3
npm install
npm start
then visit localhost:3000/ and you can create an account and login, tested on Ubuntu 20.10. Data is stored on persistently.
TODO how to merge those two repos into a single repo.
If you disable JavaScript on Chromium, it stops working completely. There is a section on how to solve that at: docs.feathersjs.com/cookbook/express/view-engine.html but it does not cover React specifically. Codaisseur/feathersjs-react-redux-ssr might be good to look into.
Also webpack and Babel, looks promising!
As of 2021, last commit from 2017.
Running:
git clone https://github.com/Codaisseur/feathersjs-react-redux-ssr
cd feathersjs-react-redux-ssr
npm install
failed on Ubuntu 20.10 Node.js v14.15.3 with:
../src/create_string.cpp:17:37: error: no matching function for call to ‘v8::String::Utf8Value::Utf8Value(v8::Local<v8::Value>&)’
   17 |   v8::String::Utf8Value string(value);
      |                                     ^
Likely similar bullshit from: stackoverflow.com/questions/50111688/node-sqlite-node-gyp-build-error-no-member-named-forceset-in-v8object because the Node.js version is too new.
If I try nvm install v10
I Google error messages until reaching:
diff --git a/gulpfile.js b/gulpfile.js
index b931e06..24d2cc8 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -14,34 +14,34 @@ gulp.task('css', function() {
            .pipe(gulp.dest('./dist'))
 })
 
-gulp.task('css:watch', ['css'], function() {
+gulp.task('css:watch', gulp.series('css', function() {
   gulp.watch('app/styles/**/*.sass', ['css'])
-})
+}))
 
 gulp.task('moveAssets', function() {
   return gulp.src('./app/assets/**/*')
              .pipe(gulp.dest('./dist/assets'))
 })
 
-gulp.task('build:revAssets', ['css', 'moveAssets'], function() {
+gulp.task('build:revAssets', gulp.series('css', 'moveAssets', function() {
   var rev = new $.revAll()
   return gulp.src('./dist/**/*')
              .pipe(rev.revision())
              .pipe(gulp.dest('./dist/public'))
              .pipe(rev.manifestFile())
              .pipe(gulp.dest('./dist'))
-})
+}))
 
 gulp.task('build:cpServer', function() {
   return gulp.src('./app/**/*.{js,ejs}')
              .pipe(gulp.dest('./dist/server-build'))
 })
-gulp.task('build:revServer', ['build:cpServer'], function() {
+gulp.task('build:revServer', gulp.series('build:cpServer', function() {
   var manifest = gulp.src('./dist/rev-manifest.json')
   return gulp.src('./dist/server-build/{components,containers}/**/*')
              .pipe($.revReplace({ manifest: manifest }))
              .pipe(gulp.dest('./dist/server-build'))
-})
+}))
 
 gulp.task('build', function() {
   runSequence('build:revAssets', 'build:revServer')
diff --git a/package.json b/package.json
index bcb29c3..86bd593 100644
--- a/package.json
+++ b/package.json
@@ -67,7 +67,7 @@
     "redux-thunk": "^0.1.0",
     "request": "^2.79.0",
     "rewire": "^2.3.4",
-    "run-sequence": "^1.2.2",
+    "run-sequence": "^2.2.1",
     "serve-favicon": "^2.3.2",
     "socket.io-client": "^1.7.2",
     "superagent": "^1.4.0",
@@ -86,16 +86,16 @@
     "concurrently": "^2.0.0",
     "cross-env": "^1.0.7",
     "enzyme": "^2.3.0",
-    "gulp": "^3.9.0",
+    "gulp": "^4.0.2",
     "gulp-autoprefixer": "^3.1.0",
     "gulp-load-plugins": "^1.2.0",
     "gulp-rev": "^6.0.1",
-    "gulp-sass": "^2.1.1",
+    "gulp-sass": "4.1.0",
     "gulp-sourcemaps": "^1.6.0",
     "jsdom": "^7.0.1",
     "mocha": "^2.4.5",
     "nock": "^2.17.0",
-    "node-sass": "^3.4.2",
+    "node-sass": "^5.0.0",
     "nodemon": "^1.6.0",
     "react-addons-test-utils": "^15.3.2",
     "react-transform-catch-errors": "^1.0.0",
and the next problem is: stackoverflow.com/questions/48513573/gulp-error-gulp-hastask-is-not-a-function
MongoDB-based.
So once you install MongoDB, run with:
MONGODB_FEATHERS_REALWORLD=mongodb://localhost:27017/mydb npm start
Tests can be run with:
MONGODB_FEATHERS_REALWORLD=mongodb://localhost:27017/mydb npm run test
but there were 10 failures and 55 passes: github.com/randyscotsmithey/feathers-realworld-example-app/issues/3
One major step was to port to PostgreSQL as shown at feathers-chat PostgreSQL.
There's also a heroku branch at: github.com/feathersjs/feathers-chat/tree/heroku, but it also seems to use NeDB? So you can have a filesystem in Heroku? Doesn't seem so: stackoverflow.com/questions/42775418/heroku-local-persistent-storage
The idea is cool. It really unifies front-and back end.
But Ciro Santilli feels the approach proposed by FeathersJS of being a glue between bigger third-party Front-end web frameworks like React and backend (object-relational mapping) is more promising and flexible.
Didn't manage to get it to work perfectly on Ubuntu 20.10: github.com/lujakob/nestjs-realworld-example-app/issues/57
Tried a quick port to SQLite to get rid of annoying local databases for development, but failed, at c1c2cc4e448b279ff083272df1ac50d20c3304fa
npm install sqlite3 --save-dev
and
{
  "type": "sqlite",
  "database": "db.sqlite3",
  "entities": ["src/**/**.entity{.ts,.js}"],
  "synchronize": true
}
then:
npm start
fails with:
DataTypeNotSupportedError: Data type "timestamp" in "ArticleEntity.created" is not supported by "sqlite" database.
Attempt to hack it:
--- a/src/article/article.entity.ts
+++ b/src/article/article.entity.ts
@@ -20,10 +20,10 @@ export class ArticleEntity {
   @Column({default: ''})
   body: string;

-  @Column({ type: 'timestamp', default: () => "CURRENT_TIMESTAMP"})
+  @Column({ default: () => "CURRENT_TIMESTAMP"})
   created: Date;

-  @Column({ type: 'timestamp', default: () => "CURRENT_TIMESTAMP"})
+  @Column({ default: () => "CURRENT_TIMESTAMP"})
   updated: Date;
and after that it seems to run.
I can signup and login, terrible error reporting as usual, make sure to use long enough usernames/passwords.
However, article creation fails with:
Unhandled Rejection (TypeError): Cannot read property 'slug' of undefined
TypeScript is good. It does find errors in your JavaScript. But it is a form of "turd polishing". But Ciro Santilli would rather have a polished turd than a non-polished one.
Part of the reason TypeScript became popular is due to the universality of asset bundlers. Once you are already using an asset bundler, changing the .js extension into .ts to get a less shitty experience is an easy choice.
The other big reason is that JavaScript is so lose with type conversions, notably undefined happily converting to strings without problems, and any missing properties of Object happily being undefined. We should actually use ES6 Map everywhere instead of using Objects as maps.
Since TypeScript is not the default form of the language however, it inevitably happens that you need to add external types for a gazillion projects that are using raw JavaScript, and sometimes fight a lot to get things to work. And so we have: github.com/DefinitelyTyped/DefinitelyTyped. Not sure if this is beautiful, or frightening.
But in the end, as with other type of static linters, TypeScript generally transforms a few hard to debug runtime issues, into a bunch of stupid to solve compile time issues, which is generally a good thing.
The fact that this it parses comments JSDoc comments in JavaScript files is quite amazing.
Examples under typescript. Run each one of them with:
npx tsc example.ts
node example.js
Helper:
tsr() (
  # ts Run
  f="$1"
  npx tsc "$f"
  node "${f%.*}.js"
)
tsr example.ts
Some major annoyances of TypeScript:
Since JavaScript devs are incapable of defining an unified import standard, this design pattern emerged where you just check every magic global one by one. Here's a demo where a Js library works on both the browser and from Node.js:

Articles by others on the same topic (0)

There are currently no matching articles.