$ node-js-greenhorn-workshopper
function sampleCode(request, response) {
if (request.path.indexOf("Is it readable?") !== -1) {
usersService.getAnswer(request.path, function (error, answer) {
if (answer === "YES") {
response.setStatusCode(200);
response.send("Move forward.");
} else {
//
// It is not acceptable!
//
response.setStatusCode(406);
response.send("Increase font size.");
}
});
}
}
$ touch NEW_FILE
$ mv SOURCE DESTINATION
$ cp SOURCE DESTINATION
$ rm -ri FILES_FOR_DELETING
$ cp /path/{1,2,3}.txt DESTINATION
$ mv /path/*.tar.gz DESTINATION
$ cat BIG_FILE | grep -i CASE_INSENSITIVE_TEXT
$ find DIRECTORY -iname *CASE_INSENSITIVE_PART_OF_NAME"
$ nohup ./run-in-background &
$ ./run-script.sh > /dev/null
$ curl -X POST -d "DATA" "http://localhost:8080/my/rest/api"
$ netcat sql-server-hostname 1433
$ wget -O OUTPUT_FILE http://http/address/to/file
$ git --version
$ git config --global user.name "Jasiu Nowak"
$ git config --global user.email "jnowak@company.com"
$ node --version # Sometimes: nodejs
$ npm --version
$ nvm
$ npm install -g jshint grunt-cli istanbul
$ git clone git@github.com:afronski/mighty-penguins-revenge.git
$ git clone git@github.com:afronski/node-js-greenhorn-workshopper.git
$ cd node-js-greenhorn-workshopper
$ npm install -g
$ node-js-greenhorn-workshopper
"use strict";
const PI = 3.14;
var util = require("util");
function Animal(options) {}
function Dog(options) {
Animal.call(this, options);
}
util.inherits(Dog, Animal);
var doge = Object.create(Dog.prototype),
doggyDoge = new Dog();
"use strict";
var http = require("http"),
links = [ "http://first-link.com", "http://second-link.com" ],
loaded;
function isTrue(element) { return element === true; }
function loaded(index, response) {
loaded[index] = (response.statusCode === 200);
if (loaded.every(isTrue)) {
console.log("All links downloaded successfully!");
}
}
loaded = links.map(function (link, index) {
http.get(link, loaded.bind(null, index));
return false;
});
"dependencies": {
"underscore": "~1.3.0"
},
"devDependencies": {
"mocking-framework": "1.x.x"
}
src
, libraries
JavaScript filesimages
Imagessounds
, music
Sound and music filesstylesheets
CSS and Fontsclient
HTML files
$ cd mighty-penguins-revenge
$ git checkout tags/TASK_1
$ npm install
An open source, on-disk, key-value store
written and maintained by Google
{
"key1": "value1",
"key2": "value2"
}
$ cd mighty-penguins-revenge
$ git checkout tags/TASK_2
$ npm install
// 1. First invoke an action.
asynchronousAction(parameters, function continuation(error, result) {
// 3. After a while, results will arrive.
});
// 2. Return from asynchronous action.
Pure JavaScript is Unicode friendly but not nice to binary data.
var buffer = new Buffer(256),
length = buffer.write("\u00bd + \u00bc = \u00be", 0);
console.log(length + " bytes: " + buffer.toString("utf8", 0, length));
Buffer.byteLength("JS string length returns characters count.", "utf8");
$ cd mighty-penguins-revenge
$ git checkout tags/TASK_3
$ npm install
fs.readFile("/path/to/file", function (error, buffer) {
/*...*/
});
fs.readFile("/path/to/file", "utf8", function (error, string) {
/*...*/
});
$ cat file.txt | grep "CONTENT" | wc -l
$ ./script 2>&1 >/dev/null | tee DIFFERENT_FILE.txt
We should have some ways of connecting programs like garden hose--screw in another segment when it becomes necessary to massage data in another way.Doug McIlroy, 1964
// Different types of streams:
// - Readable and Writable
// - Transform and PassThrough
// - Duplex
stream.on("data", function (chunk) { /*...*/ });
stream.on("end", function () { /*...*/ });
stream.on("error", function () { /*...*/ });
from.pipe(to);
readable.pipe(writable);
Push as a HTTP
response previously cached file
from memory storage.
$ cd mighty-penguins-revenge
$ git checkout tags/TASK_4
$ npm install
cache.exposeStream(file).pipe(response);
asynchronousAction(parameters, function (error, results) {
if (error) {
continuation(error);
return;
}
asynchronousAction(parameters, function (error) {
if (error) {
continuation(error);
return;
}
asynchronousAction(function (error, results) {
if (error) {
continuation(error);
return;
}
// WTF ???
Domains provide a way to handle multiple different I/O operations as a single group.
$ cd mighty-penguins-revenge
$ git checkout tags/TASK_5
$ npm install
var domain = require("domain"),
handler = domain.create();
handler.on("error", function (error) { /*...*/ });
asynchronousAction(parameters, handler.intercept(function (results) {
asynchronousAction(parameters, handler.intercept(function () {
asynchronousAction(handler.intercept(function (results) {
/*...*/
}));
}));
}));
var util = require("util"),
EventEmitter = require("events").EventEmitter,
sender;
function Sender() {
EventEmitter.call(this);
}
util.inherits(Sender, EventEmitter);
sender = new Sender();
sender.on("eventName", function handler() { /*...*/ });
sender.addListener("eventName", function handler() { /*...*/ });
sender.once("eventName", function handler() { /*...*/ });
sender.removeAllListeners();
sender.removeListener("eventName", handler);
sender.emit("eventName", argument1 /* ... */);
$ cd mighty-penguins-revenge
$ git checkout tags/TASK_6
$ npm install
socket.get("room-author", function (error, isAuthor) {
owner.queries.getAccessibleRooms(function (error, rooms) {
rooms = rooms.filter(bySession.bind(null, session))[0];
if (rooms) {
if (isAuthor) {
owner.commands.lockRoom(session, function (error) {
socket.broadcast.to(session).emit("game-started");
});
}
} else {
socket.emit("game-failed");
}
});
});
A protocol providing full-duplex communications channels over a single TCP connection. The WebSocket protocol was standardized by the IETF as RFC 6455 in 2011, and the WebSocket API in Web IDL is being standardized by the W3C.
socket.join("room");
socket.leave("room");
socket.set("property", /*...*/);
socket.get("property", /*...*/);
socketIO.of("/rooms").on("event-name", function handler() { /*...*/ });
socket.broadcast.to("room").emit("event-name", /*...*/);
socket.broadcast.emit("event-name", /*...*/);
socket.emit("event-name", /*...*/);
$ cd mighty-penguins-revenge
$ git checkout tags/TASK_7
$ npm install
function broadcastPlayerState(socket, session, state) {
socket.broadcast.to(session).emit("enemy-update", state);
};
function broadcastPlayerBullet(socket, session, nick) {
socket.broadcast.to(session).emit("new-bullet", nick);
};
Separate compute intensive parts from client-facing parts.
Separate potentially dangerous parts from client-facing parts.
promise
.then(function onSuccess() { /*...*/ })
.error(function onFailure() { /*...*/ });
var fs = require("q-io/fs"),
readJsonPromise = Q.async(function *(path) {
return JSON.parse(yield fs.read(path));
});
Q
It models just one question and one answer.
userService.getUsers(/*...*/)
.then(function onSuccess() { /*...*/ })
.error(function onFailure() { /*...*/ });
function wait(ms, value callback) {
setTimeout(function () {
callback(null, value);
}, ms);
}
async.parallel([
wait.bind(null, 200, "one"),
wait.bind(null, 100, "two")
],
function (error, results) {
// The results array will equal [ "one", "two" ] even though
// the second function had a shorter timeout.
});
async
$ cd mighty-penguins-revenge
$ git checkout tags/TASK_8
$ npm install
owner.commands.updateScore(session, nick, score, function (error, score) {
if (score >= owner.settings.MaximumScore) {
owner.commands.closeContest(session, function (error) {
owner.commands.deleteRoom(session, function (error) {
socket.emit("game-finished");
socket.broadcast.to(session).emit("game-finished");
});
});
}
});
A supervisor is responsible for starting, stopping and monitoring its child processes.
The basic idea of a supervisor is that it should keep its child processes alive by restarting them when necessary.
$ npm install -g forever
$ cd mighty-penguins-revenge
$ git checkout tags/TASK_9
$ npm install
$ forever --help
#!/bin/sh
forever --minUptime 1000 --spinSleepTime 1000
-e server/logs/error.log -o server/logs/normal.log
index.js --no-colors
$ cd mighty-penguins-revenge
$ git checkout master
$ npm install