├── .gitignore ├── LICENSE ├── README.md ├── data ├── readable.text ├── transform.text └── writeable.text ├── index.js ├── package.json ├── src ├── 01-What_is_Node │ └── README.md ├── 02-Working_with_npm_and_modules │ ├── README.md │ ├── module_1 │ │ ├── README.md │ │ ├── index.js │ │ └── package.json │ └── module_2 │ │ ├── README.md │ │ ├── index.js │ │ └── package.json ├── 03-Node_Concepts │ ├── README.md │ ├── buffers.js │ ├── events.js │ ├── stream.js │ └── streams │ │ ├── duplex.js │ │ ├── readable.js │ │ ├── transform.js │ │ └── writable.js ├── 04-Working_with_Express │ ├── README.md │ ├── express-domain.js │ └── express.js ├── 05-Working_with_the_Process_API │ ├── README.md │ └── process.js ├── 06-Error_Handling │ ├── README.md │ ├── domain.js │ └── errors.js ├── 07-Sockets │ ├── README.md │ ├── websocket.html │ └── websocket.js ├── 08-Clustering_and_Multi-Process │ ├── README.md │ ├── cluster-domain.js │ ├── cluster.js │ └── workers │ │ ├── domain-worker.js │ │ └── worker1.js ├── 09-Deployment │ └── README.md └── 10-Troubleshooting │ ├── README.md │ └── repl.js └── utils.js /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | *.log -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Vincenzo Ferrari 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | node-certification 2 | ================== 3 | 4 | SCND Strongloop Certification Exam work out 5 | 6 | ## Info about the exam 7 | 8 | - [SCND](http://strongloop.com/node-js/certification) 9 | - [SCND FAQ](http://strongloop.com/node-js/certification/faq) 10 | - [SCND Study Guide](http://strongloop.com/node-js/certification/scnd-study-guide) 11 | - [Additional Resources](https://github.com/rockbot/node-for-beginners) 12 | 13 | ## About this repo 14 | 15 | Every file contains one or more exercise for a particular node topic, like buffer, domain, cluster and so on. 16 | All the exercises are organized by folders for each of the concepts covered in the exam. 17 | 18 | To try it out, just launch it with node in the following way: 19 | 20 | ```bash 21 | $ node src/03-Node_Concepts/buffers.js 22 | ``` 23 | 24 | or use the interactive menu: 25 | 26 | ```bash 27 | $ npm start 28 | ``` 29 | 30 | And watch the output and later open files to study the code :) 31 | 32 | ## Contribute 33 | I know that could be some error so if you find any please provide to fix them with a pull request. 34 | To contrib use [pull requests](https://help.github.com/articles/using-pull-requests/). 35 | 36 | ## License 37 | [Read the LICENSE file (MIT, anyway)](../../LICENSE) 38 | -------------------------------------------------------------------------------- /data/readable.text: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede sit amet augue. In turpis. Pellentesque posuere. Praesent turpis. Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum mollis diam. Pellentesque ut neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac felis quis tortor malesuada pretium. Pellentesque auctor neque nec urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna. In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis vulputate lorem. Morbi nec metus. Phasellus blandit leo ut odio. Maecenas ullamcorper, dui et placerat feugiat, eros pede varius nisi, condimentum viverra felis nunc et lorem. Sed magna purus, fermentum eu, tincidunt eu, varius ut, felis. In auctor lobortis lacus. Quisque libero metus, condimentum nec, tempor a, commodo mollis, magna. Vestibulum ullamcorper mauris at ligula. Fusce fermentum. Nullam cursus lacinia erat. Praesent blandit laoreet nibh. Fusce convallis metus id felis luctus adipiscing. Pellentesque egestas, neque sit amet convallis pulvinar, justo nulla eleifend augue, ac auctor orci leo non est. Quisque id mi. Ut tincidunt tincidunt erat. Etiam feugiat lorem non metus. Vestibulum dapibus nunc ac augue. Curabitur vestibulum aliquam leo. Praesent egestas neque eu enim. In hac habitasse platea dictumst. Fusce a quam. Etiam ut purus mattis mauris sodales aliquam. Curabitur nisi. Quisque malesuada placerat nisl. Nam ipsum risus, rutrum vitae, vestibulum eu, molestie vel, lacus. Sed augue ipsum, egestas nec, vestibulum et, malesuada adipiscing, dui. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi congue nunc, vitae euismod ligula urna in dolor. Mauris sollicitudin fermentum libero. Praesent nonummy mi in odio. Nunc interdum lacus sit amet orci. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi. Morbi mollis tellus ac sapien. Phasellus volutpat, metus eget egestas mollis, lacus lacus blandit dui, id egestas quam mauris ut lacus. Fusce vel dui. Sed in libero ut nibh placerat accumsan. Proin faucibus arcu quis ante. In consectetuer turpis ut velit. Nulla sit amet est. Praesent metus tellus, elementum eu, semper a, adipiscing nec, purus. Cras risus ipsum, faucibus ut, ullamcorper id, varius ac, leo. Suspendisse feugiat. Suspendisse enim turpis, dictum sed, iaculis a, condimentum nec, nisi. Praesent nec nisl a purus blandit viverra. Praesent ac massa at ligula laoreet iaculis. Nulla neque dolor, sagittis eget, iaculis quis, molestie non, velit. Mauris turpis nunc, blandit et, volutpat molestie, porta ut, ligula. Fusce pharetra convallis urna. Quisque ut nisi. Donec mi odio, faucibus at, scelerisque quis, 2 | 3 | -------------------------------------------------------------------------------- /data/transform.text: -------------------------------------------------------------------------------- 1 | **Readi** 2 | **Readi** 3 | -------------------------------------------------------------------------------- /data/writeable.text: -------------------------------------------------------------------------------- 1 | 2 | 3 | DONE -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // Based on: https://www.npmjs.com/package/node-menu 2 | 3 | 'use strict'; 4 | 5 | var menu = require('node-menu'); 6 | var utils = require('./utils'); 7 | 8 | var pointers = []; 9 | 10 | menu 11 | .addDelimiter('-', 40, 'SCND Node Certified Program') 12 | 13 | // 01-What_is_Node // ---------------------------------------------------------------------- 14 | 15 | // 02-Working_with_npm_and_modules // ------------------------------------------------------ 16 | .addItem( 17 | 'Working with NPM and modules? - Modules Exercise', 18 | function() { pointers = utils.runScript('src/02-Working_with_npm_and_modules/module_2/index.js', pointers, utils.cleanCallback); } 19 | ) 20 | 21 | // 03-Node_Concepts // --------------------------------------------------------------------- 22 | .addItem( 23 | 'Node Concepts - Events Exercise', 24 | function() { pointers = utils.runScript('src/03-Node_Concepts/events.js', pointers, utils.cleanCallback); } 25 | ) 26 | .addItem( 27 | 'Node Concepts - Stream Exercise', 28 | function() { pointers = utils.runScript('src/03-Node_Concepts/stream.js', pointers, utils.cleanCallback); } 29 | ) 30 | .addItem( 31 | 'Node Concepts - Buffer Exercise', 32 | function() { pointers = utils.runScript('src/03-Node_Concepts/buffers.js', pointers, utils.cleanCallback); } 33 | ) 34 | 35 | // 04-Working_with_Express // -------------------------------------------------------------- 36 | .addItem( 37 | 'Working with Express - Express Exercise', 38 | function() { pointers = utils.runScript('src/04-Working_with_Express/express.js', pointers, utils.cleanCallback); } 39 | ) 40 | .addItem( 41 | 'Working with Express - Express with domain Exercise', 42 | function() { pointers = utils.runScript('src/04-Working_with_Express/express-domain.js', pointers, utils.cleanCallback); } 43 | ) 44 | 45 | // 05-Working_with_the_Process_API // ------------------------------------------------------ 46 | .addItem( 47 | 'Working with the process API - Process Exercise', 48 | function() { pointers = utils.runScript('src/05-Working_with_the_Process_API/process.js', pointers, utils.cleanCallback); } 49 | ) 50 | 51 | // 06-Error_Handling // -------------------------------------------------------------------- 52 | .addItem( 53 | 'Error Handling - Domain Exercise', 54 | function() { pointers = utils.runScript('src/06-Error_Handling/domain.js', pointers, utils.cleanCallback); } 55 | ) 56 | 57 | .addItem( 58 | 'Error Handling - Error Exercise', 59 | function() { pointers = utils.runScript('src/06-Error_Handling/errors.js', pointers, utils.cleanCallback); } 60 | ) 61 | 62 | // 07-Sockets // --------------------------------------------------------------------------- 63 | .addItem( 64 | 'Sockets - WebSockets Exercise', 65 | function() { pointers = utils.runScript('src/07-Sockets/websocket.js', pointers, utils.cleanCallback); } 66 | ) 67 | 68 | // 08-Clustering_and_Multi-Process // ------------------------------------------------------ 69 | .addItem( 70 | 'Clustering and Multi-Process - Exercise', 71 | function() { pointers = utils.runScript('src/08-Clustering_and_Multi-Process/cluster.js', pointers, utils.cleanCallback); } 72 | ) 73 | .addItem( 74 | 'Clustering and Multi-Process - Cluster Domain Exercise', 75 | function() { pointers = utils.runScript('src/08-Clustering_and_Multi-Process/cluster-domain.js', pointers, utils.cleanCallback); } 76 | ) 77 | 78 | // 09-Deployment // ------------------------------------------------------------------------ 79 | 80 | // 10-Troubleshooting // ------------------------------------------------------------------- 81 | .addItem( 82 | 'Troubleshooting - REPL Exercise', 83 | function() { pointers = utils.runScript('src/10-Troubleshooting/repl.js', pointers, utils.cleanCallback); } 84 | ) 85 | 86 | .customHeader(function() { 87 | process.stdout.write("███████╗ ██████╗███╗ ██╗██████╗\n" + 88 | "██╔════╝██╔════╝████╗ ██║██╔══██╗\n" + 89 | "███████╗██║ ██╔██╗ ██║██║ ██║\n" + 90 | "╚════██║██║ ██║╚██╗██║██║ ██║\n" + 91 | "███████║╚██████╗██║ ╚████║██████╔╝\n" + 92 | "╚══════╝ ╚═════╝╚═╝ ╚═══╝╚═════╝\n\n"); 93 | process.stdout.write("Strongloop Certification Node Certification - Exam work out\n\n"); 94 | }) 95 | 96 | .addDelimiter('-', 40) 97 | .start(); 98 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-certification", 3 | "version": "0.0.1", 4 | "description": "SCND Certification Program", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "Vincenzo (Wilk) Ferrari ", 11 | "contributors": [ 12 | { 13 | "name": "Manuel E. de Paz Carmona", 14 | "email": "Pelirrojo@users.noreply.github.com" 15 | } 16 | ], 17 | "license": "MIT", 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/wilk/node_certification" 21 | }, 22 | "dependencies": { 23 | "async": "^1.5.0", 24 | "bunyan": "^1.0.0", 25 | "express": "^4.13.3", 26 | "express-bunyan-logger": "^0.2.2", 27 | "node-menu": "0.0.9", 28 | "q": "^1.4.1", 29 | "socket.io": "^1.3.7" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/01-What_is_Node/README.md: -------------------------------------------------------------------------------- 1 | node-certification 2 | ================== 3 | 4 | SCND Strongloop Certification Exam work out 5 | 6 | # What is node? 7 | 8 | Node.js is a platform built on Chrome’s JavaScript runtime for easily building fast, scalable network applications. 9 | Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices. The exam will test your basic understanding of Node’s architecture, its main components (APIs, bindings, V8 and libuv), and how they interact. 10 | 11 | * [V8 JavaScript engine](http://strongloop.com/developers/videos/#a-video-intro-to-how-node-works) 12 | * [libuv: cross platform asynchronous I/O for Node](https://github.com/libuv/libuv) 13 | * [APIs](http://nodejs.org/api) 14 | 15 | There are two additional videos worth watching that introduce the fundamentals of Node: 16 | * [How Node works](http://strongloop.com/developers/videos/#a-video-intro-to-how-node-works) 17 | * [Node fundamentals](https://strongloop.com/node-js/videos/#a-video-intro-to-nodejs-fundamentals) 18 | 19 | ## Content 20 | 21 | No exercises by the moment sorry :( 22 | To contrib use [pull requests](https://help.github.com/articles/using-pull-requests). 23 | 24 | ## License 25 | [Read the LICENSE file (MIT, anyway)](../../LICENSE) 26 | 27 | ## Reference 28 | [http://strongloop.com/node-js/certification/scnd-study-guide/](http://strongloop.com/node-js/certification/scnd-study-guide/) 29 | -------------------------------------------------------------------------------- /src/02-Working_with_npm_and_modules/README.md: -------------------------------------------------------------------------------- 1 | node-certification 2 | ================== 3 | 4 | SCND Strongloop Certification Exam work out 5 | 6 | # Working with npm and node Modules 7 | 8 | [Npm](http://en.wikipedia.org/wiki/Npm_(software)) is the official package manager for Node written in JavaScript. npm runs through the command line and manages dependencies for an application with package.json. 9 | It also allows users to install Node modules that are available on the npm registry. The exam will test your understanding of npm. 10 | 11 | * [package.json](https://docs.npmjs.com/files/package.json) 12 | * [How to find, install, update and publish packages](https://docs.npmjs.com/misc/developers) 13 | 14 | ## Content 15 | 16 | * ./module_1/index.js & ./module_2/index.js 17 | 18 | ## Instructions 19 | 20 | Specific guide for this section. 21 | 22 | ### Linking 23 | 24 | Open a terminal and type as follows: 25 | 26 | ```bash 27 | $ cd module_1 28 | $ npm link 29 | $ cd ../module_2 30 | $ npm link module_1 31 | ``` 32 | 33 | or 34 | 35 | ```bash 36 | $ cd module_2 37 | $ npm link ../module_1 38 | ``` 39 | 40 | **module_1 will** be linked into your global node_modules (e.g.: */usr/local/lib/node_modules*) and then installed as 41 | a local dependency into **module_2/node_modules/module_1** 42 | 43 | ### Running 44 | 45 | ```bash 46 | $ cd module_2 47 | $ node index 48 | ``` 49 | 50 | ### Packing 51 | 52 | Making a package (tarball) with **npm pack**: 53 | 54 | ```bash 55 | $ cd module_1 // or module_2 56 | $ npm pack 57 | ``` 58 | 59 | A new **module_1.tar.gz** will be added into module_1 folder, containing your package 60 | 61 | ## License 62 | [Read the LICENSE file (MIT, anyway)](../../LICENSE) 63 | 64 | ## Reference 65 | [http://strongloop.com/node-js/certification/scnd-study-guide/](http://strongloop.com/node-js/certification/scnd-study-guide/) 66 | -------------------------------------------------------------------------------- /src/02-Working_with_npm_and_modules/module_1/README.md: -------------------------------------------------------------------------------- 1 | node-certification 2 | ================== 3 | 4 | SCND Strongloop Certification Exam work out 5 | 6 | Module 1 to show a message when it's required 7 | 8 | ## License 9 | [Read the LICENSE file (MIT, anyway)](../../LICENSE) 10 | 11 | ## Reference 12 | [http://strongloop.com/node-js/certification/scnd-study-guide/](http://strongloop.com/node-js/certification/scnd-study-guide/) 13 | -------------------------------------------------------------------------------- /src/02-Working_with_npm_and_modules/module_1/index.js: -------------------------------------------------------------------------------- 1 | module.exports = "Hi I'm module_1! Hello world!"; -------------------------------------------------------------------------------- /src/02-Working_with_npm_and_modules/module_1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "module_1", 3 | "version": "0.0.0", 4 | "description": "Say hello World", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": "", 10 | "author": "", 11 | "license": "MIT" 12 | } 13 | -------------------------------------------------------------------------------- /src/02-Working_with_npm_and_modules/module_2/README.md: -------------------------------------------------------------------------------- 1 | node-certification 2 | ================== 3 | 4 | SCND Strongloop Certification Exam work out 5 | 6 | Module 2 to require the Module 1 7 | 8 | ## License 9 | [Read the LICENSE file (MIT, anyway)](../../LICENSE) 10 | 11 | ## Reference 12 | [http://strongloop.com/node-js/certification/scnd-study-guide/](http://strongloop.com/node-js/certification/scnd-study-guide/) 13 | -------------------------------------------------------------------------------- /src/02-Working_with_npm_and_modules/module_2/index.js: -------------------------------------------------------------------------------- 1 | var m1 = require('../module_1'); 2 | 3 | console.log("Hi I'm module_2 and I've just required module_1. Here it comes!"); 4 | console.log(m1); 5 | -------------------------------------------------------------------------------- /src/02-Working_with_npm_and_modules/module_2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "module_2", 3 | "version": "0.0.0", 4 | "description": "Require the module 1", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": "", 10 | "author": "", 11 | "license": "MIT" 12 | } 13 | -------------------------------------------------------------------------------- /src/03-Node_Concepts/README.md: -------------------------------------------------------------------------------- 1 | node-certification 2 | ================== 3 | 4 | SCND Strongloop Certification Exam work out 5 | 6 | # Node Concepts 7 | 8 | The exam will test your knowledge of these core Node concepts: 9 | 10 | * [Event loop](http://strongloop.com/strongblog/node-js-event-loop): An event loop is “an entity that handles and processes external events and converts them into callback invocations”. 11 | * [Callbacks](http://strongloop.com/strongblog/node-js-callback-hell-promises-generators): At an I/O call, your code saves the callback and returns control to the runtime environment. The callback will be called later when the data actually is available. 12 | * [Event emitters](http://docs.nodejitsu.com/articles/getting-started/control-flow/what-are-event-emitters): In Node.js an event can be described simply as a string with a corresponding callback. An event can be “emitted” (or in other words, the corresponding callback be called) multiple times or you can choose to only listen for the first time it is emitted. 13 | * [Streams](http://maxogden.com/node-streams.html): The main tool in Node’s evented toolbox is the Stream. Stream instances are basically Unix pipes. They can be readable, writable or both. 14 | * [Buffers](http://docs.nodejitsu.com/articles/advanced/buffers/how-to-use-buffers): Buffers are instances of the Buffer class in Node, which is designed to handle raw binary data. Each buffer corresponds to some raw memory allocated outside V8. 15 | * [JavaScript closures](http://howtonode.org/why-use-closure): A closure is an inner function that has access to the outer (enclosing) function’s variables—scope chain. 16 | 17 | ## Content 18 | 19 | * ./buffers.js 20 | * ./events.js 21 | * ./stream.js 22 | * ./streams/duplex.js 23 | * ./streams/readable.js 24 | * ./streams/transform.js 25 | * ./streams/writable.js 26 | 27 | ## License 28 | [Read the LICENSE file (MIT, anyway)](../../LICENSE) 29 | 30 | ## Reference 31 | [http://strongloop.com/node-js/certification/scnd-study-guide/](http://strongloop.com/node-js/certification/scnd-study-guide/) 32 | -------------------------------------------------------------------------------- /src/03-Node_Concepts/buffers.js: -------------------------------------------------------------------------------- 1 | 2 | var buf = new Buffer('hello world ☃', 'utf-8'); 3 | console.log(buf.toString()); 4 | console.log('Buffer lenght ' + buf.length); 5 | console.log('String byteLength ' + Buffer.byteLength(buf.toString())); 6 | console.log('String length ' + buf.toString().length); 7 | 8 | var buf2 = new Buffer(1024); // 1KB 9 | buf2.write('Hello world! ☃', 'utf-8'); 10 | 11 | console.log(buf2.toString()); 12 | console.log('Buffer length ' + buf2.length); 13 | console.log('String length ' + buf2.toString().length); 14 | 15 | var buf3 = new Buffer('Winter is coming!', 'utf-8'); 16 | 17 | buf3.copy(buf2, 17); 18 | 19 | console.log(buf3.toString()); 20 | console.log(buf2.toString()); 21 | 22 | var aBuf = new Buffer('Dude', 'utf-8'), 23 | bBuf = new Buffer('Dude', 'utf-8'); 24 | 25 | console.log('Checking if aBuff its equal to bBuff'); 26 | console.log(aBuf.toString() === bBuf.toString()); 27 | 28 | -------------------------------------------------------------------------------- /src/03-Node_Concepts/events.js: -------------------------------------------------------------------------------- 1 | var events = require('events'), 2 | util = require('util'), 3 | EventEmitter = events.EventEmitter; 4 | 5 | var Observed = function () {}; 6 | 7 | util.inherits(Observed, EventEmitter); 8 | 9 | Observed.prototype.text = function (text) { 10 | this.emit('message', text); 11 | }; 12 | 13 | Observed.prototype.json = function (object) { 14 | this.emit('json', object); 15 | }; 16 | 17 | var o1 = new Observed(); 18 | 19 | o1.on('message', function (text) { 20 | console.log('Listener#1: A new text message is arrived: ' + text); 21 | }); 22 | 23 | o1.on('message', function (text) { 24 | console.log('Listener#2: A new text message is arrived: ' + text); 25 | }); 26 | 27 | o1.on('json', function (object) { 28 | console.log('A new object message is arrived:'); 29 | console.log(util.inspect(object)); 30 | }); 31 | 32 | o1.text('hello world!'); 33 | o1.json({ 34 | hello: 'world' 35 | }); 36 | 37 | console.log('Listeners attached to the message event: ' + EventEmitter.listenerCount(o1, 'message')); 38 | console.log('Listeners attached to the json event: ' + EventEmitter.listenerCount(o1, 'json')); -------------------------------------------------------------------------------- /src/03-Node_Concepts/stream.js: -------------------------------------------------------------------------------- 1 | var stream = require('stream'), 2 | Readable = stream.Readable, 3 | Writable = stream.Writable, 4 | Duplex = stream.Duplex, 5 | Transform = stream.Transform, 6 | util = require('util'), 7 | fs = require('fs'), 8 | readableStreamCounter = 0; 9 | 10 | function ReadableStream (cfg) { 11 | Readable.call(this, cfg); 12 | 13 | this._data = cfg.data || {}; 14 | } 15 | 16 | util.inherits(ReadableStream, Readable); 17 | 18 | ReadableStream.prototype._read = function (chunkSize) { 19 | chunkSize = 50; 20 | 21 | var self = this; 22 | 23 | if (readableStreamCounter < self._data.length) { 24 | if ((self._data.length - readableStreamCounter) < chunkSize) { 25 | self.push(self._data.slice(readableStreamCounter, (self._data.length - readableStreamCounter))); 26 | readableStreamCounter += (self._data.length - readableStreamCounter); 27 | } 28 | else { 29 | self.push(self._data.slice(readableStreamCounter, readableStreamCounter + chunkSize)); 30 | readableStreamCounter += chunkSize; 31 | } 32 | } 33 | else { 34 | self.push(); 35 | } 36 | }; 37 | 38 | function WritebleStream (cfg) { 39 | Writable.call(this, cfg); 40 | 41 | this._file = cfg.file; 42 | } 43 | 44 | util.inherits(WritebleStream, Writable); 45 | 46 | WritebleStream.prototype._write = function (chunk, encoding, callback) { 47 | console.log(typeof chunk); 48 | 49 | fs.writeFile(this._file, chunk, callback); 50 | }; 51 | 52 | function DuplexStream (cfg) { 53 | Duplex.call(this, cfg); 54 | } 55 | 56 | util.inherits(DuplexStream, Duplex); 57 | 58 | function TransformStream (cfg) { 59 | Transform.call(this, cfg); 60 | } 61 | 62 | util.inherits(TransformStream, Transform); 63 | 64 | fs.readFile('data/readable.text', {encoding: 'utf8'}, function (err, file) { 65 | if (err) throw err; 66 | 67 | var rs = new ReadableStream({ 68 | data: file, 69 | encoding: 'utf8' 70 | }); 71 | 72 | var readData = ''; 73 | 74 | rs.on('data', function (chunk) { 75 | console.log(''); 76 | console.log('Read a chunk of data'); 77 | console.log(chunk); 78 | console.log(''); 79 | readData += chunk; 80 | }); 81 | 82 | rs.on('end', function () { 83 | console.log(''); 84 | console.log('ReadableStream: read ' + readData.length + ' bytes of data from readable.text'); 85 | console.log(''); 86 | console.log(readData); 87 | console.log(''); 88 | 89 | var ws = new WritebleStream({ 90 | file: 'data/writeable.text' 91 | }); 92 | 93 | ws.write(readData); 94 | ws.end('\n\nDONE'); 95 | 96 | ws.on('finish', function () { 97 | console.log(''); 98 | console.log('WriteableStream: written all data!'); 99 | console.log(''); 100 | }); 101 | }); 102 | }); 103 | 104 | /*, 105 | ws = new me.WritebleStream({ 106 | src: 'tasks/data/readable.text', 107 | dest: 'tasks/data/writable.text' 108 | }), 109 | ds = new me.DuplexStream(), 110 | ts = new me.TransformStream({ 111 | src: 'tasks/data/transform.csv', 112 | dest: 'tasks/data/transform.json' 113 | });*/ -------------------------------------------------------------------------------- /src/03-Node_Concepts/streams/duplex.js: -------------------------------------------------------------------------------- 1 | var util = require('util'), 2 | stream = require('stream'), 3 | Duplex = stream.Duplex, 4 | fs = require('fs'); 5 | 6 | function MyDuplex (cfg) { 7 | Duplex.call(this, cfg); 8 | 9 | this._output = cfg.output; 10 | this._input = cfg.input; 11 | this._index = 0; 12 | }; 13 | 14 | util.inherits(MyDuplex, Duplex); 15 | 16 | MyDuplex.prototype._read = function () { 17 | var chunkSize = 5; 18 | 19 | if (this._input.length > this._index) { 20 | this.push(this._input.slice(this._index, this._index + chunkSize)); 21 | this._index += chunkSize; 22 | } 23 | else this.push(); 24 | }; 25 | 26 | MyDuplex.prototype._write = function (chunk, encoding, callback) { 27 | fs.writeFile(this._output, chunk, callback); 28 | }; 29 | 30 | module.exports = MyDuplex; 31 | 32 | if (require.main == module) { 33 | var ds = new MyDuplex({input: 'this is a message from the future, read bit-per-bit', output: 'tasks/data/writeable.text'}); 34 | 35 | ds.pipe(ds); 36 | 37 | ds.on('data', function (chunk) { 38 | console.log('READING CHUNK'); 39 | console.log(''); 40 | console.log(chunk.toString()); 41 | console.log(''); 42 | }); 43 | 44 | ds.on('end', function () { 45 | console.log('STOP READING'); 46 | }); 47 | 48 | ds.on('pipe', function (src) { 49 | console.log('PIPING'); 50 | assert.equal(src, ds); 51 | }); 52 | 53 | ds.on('finish', function () { 54 | console.log('STOP WRITING'); 55 | }); 56 | } -------------------------------------------------------------------------------- /src/03-Node_Concepts/streams/readable.js: -------------------------------------------------------------------------------- 1 | var stream = require('stream'), 2 | util = require('util'), 3 | ReadableStream = stream.Readable; 4 | 5 | // Read an input string 6 | 7 | var MyReadableStream = function (cfg) { 8 | ReadableStream.call(this, cfg); 9 | 10 | this._src = cfg.src; 11 | this._index = 0; 12 | }; 13 | 14 | util.inherits(MyReadableStream, ReadableStream); 15 | 16 | MyReadableStream.prototype._read = function () { 17 | var chunkSize = 5; 18 | 19 | if (this._src.length > this._index) { 20 | this.push(this._src.slice(this._index, this._index + chunkSize)); 21 | this._index += chunkSize; 22 | } 23 | else this.push(); 24 | }; 25 | 26 | module.exports = MyReadableStream; 27 | 28 | if (require.main === module) { 29 | var rs = new MyReadableStream({src: "Reading some data from a long string like this one, a static inline string, 5 byte per time"}); 30 | 31 | rs.on('data', function (chunk) { 32 | console.log('Here\'s some data:'); 33 | console.log(''); 34 | console.log(chunk.toString()); 35 | console.log(''); 36 | }); 37 | 38 | rs.on('end', function () { 39 | console.log('Finished reading data'); 40 | }); 41 | } -------------------------------------------------------------------------------- /src/03-Node_Concepts/streams/transform.js: -------------------------------------------------------------------------------- 1 | var util = require('util'), 2 | stream = require('stream'), 3 | Transform = stream.Transform, 4 | fs = require('fs'), 5 | MyReadableStream = require('./readable.js'), 6 | MyWritableStream = require('./writable.js'); 7 | 8 | function MyTransform (cfg) { 9 | Transform.call(this, cfg); 10 | } 11 | 12 | util.inherits(MyTransform, Transform); 13 | 14 | MyTransform.prototype._transform = function (chunk, encoding, callback) { 15 | console.log(chunk.toString()); 16 | this.push('**' + chunk.toString() + '**'); 17 | }; 18 | 19 | module.exports = MyTransform; 20 | 21 | if (require.main == module) { 22 | var ts = new MyTransform(), 23 | rs = new MyReadableStream({src: "Reading some data from a long string like this one, a static inline string, 5 byte per time"}), 24 | ws = new MyWritableStream({file: 'tasks/data/transform.text'}); 25 | 26 | rs.pipe(ts).pipe(ws); 27 | 28 | ts.on('finish', function () { 29 | console.log('Transform stream finished!'); 30 | }); 31 | 32 | ws.on('finish', function () { 33 | console.log('Writeable stream finished!'); 34 | }); 35 | } -------------------------------------------------------------------------------- /src/03-Node_Concepts/streams/writable.js: -------------------------------------------------------------------------------- 1 | var util = require('util'), 2 | stream = require('stream'), 3 | Writable = stream.Writable, 4 | fs = require('fs'), 5 | MyReadableStream = require('./readable'); 6 | 7 | function MyWritableStream (cfg) { 8 | Writable.call(this, cfg); 9 | 10 | this._file = cfg.file; 11 | } 12 | 13 | util.inherits(MyWritableStream, Writable); 14 | 15 | MyWritableStream.prototype._write = function (chunk, encoding, callback) { 16 | fs.appendFile(this._file, chunk + '\n', callback); 17 | }; 18 | 19 | module.exports = MyWritableStream; 20 | 21 | if (require.main == module) { 22 | var ws = new MyWritableStream({file: 'tasks/data/writeable.text'}), 23 | rs = new MyReadableStream({src: "Reading some data from a long string like this one, a static inline string, 5 byte per time"}); 24 | 25 | rs.pipe(ws); 26 | 27 | ws.on('pipe', function (src) { 28 | console.log('Someone is piping something here!'); 29 | }); 30 | 31 | ws.on('finish', function () { 32 | console.log('Finished writing!'); 33 | }); 34 | } -------------------------------------------------------------------------------- /src/04-Working_with_Express/README.md: -------------------------------------------------------------------------------- 1 | node-certification 2 | ================== 3 | 4 | SCND Strongloop Certification Exam work out 5 | 6 | # Working with Express 7 | 8 | The [Express](http://expressjs.com/) framework is arguably one of the most popular npm modules and what many developers start and build applications with. 9 | What is Express? Express is a minimal and flexible Node-based web application framework, providing a robust set of features for building single and multi-page, and hybrid web applications. For the purposes of the exam you should know how to build a basic web application using Express. 10 | 11 | ## Content 12 | 13 | * ./express.js 14 | * ./express-domain.js 15 | 16 | ## License 17 | [Read the LICENSE file (MIT, anyway)](../../LICENSE) 18 | 19 | ## Reference 20 | [http://strongloop.com/node-js/certification/scnd-study-guide/](http://strongloop.com/node-js/certification/scnd-study-guide/) 21 | -------------------------------------------------------------------------------- /src/04-Working_with_Express/express-domain.js: -------------------------------------------------------------------------------- 1 | var express = require('express'), 2 | app = express(), 3 | router = express.Router(), 4 | domain = require('domain'); 5 | 6 | app.use(function (req, res, next) { 7 | var expressDomain = domain.create(); 8 | expressDomain.add(req); 9 | expressDomain.add(res); 10 | expressDomain.on('error', next); 11 | expressDomain.run(next); 12 | 13 | console.log('DOMAIN STARTED'); 14 | }); 15 | 16 | router.route('/').get(function (req, res) { 17 | console.log('GET /'); 18 | console.log(''); 19 | 20 | process.nextTick(function () { 21 | throw new Error('An error from within!'); 22 | }); 23 | 24 | //res.status(200).send('Hello world!'); 25 | }); 26 | app.use('/api', router); 27 | 28 | app.use(function (err, req, res, next) { 29 | console.log('HERE WE ARE!'); 30 | console.log(err); 31 | console.log(err.domain); 32 | 33 | if (err.domain) { 34 | res.status(500).send('Server crashed!'); 35 | 36 | server.close(); 37 | } 38 | }); 39 | 40 | var server = app.listen(12345); 41 | console.log('Express App listening on 12345'); 42 | -------------------------------------------------------------------------------- /src/04-Working_with_Express/express.js: -------------------------------------------------------------------------------- 1 | var express = require('express'), 2 | router = express.Router(), 3 | logger = require('express-bunyan-logger'), 4 | fs = require('fs'), 5 | app = express(), 6 | repl = require('./../10-Troubleshooting/repl'); 7 | 8 | var users = ['foo', 'bar', 'foobar']; 9 | router.param('user', function (req, res, next, id) { 10 | if (id >= 0 && id < users.length) { 11 | req.user = users[id]; 12 | next(); 13 | } 14 | else next(new Error('Non existing user with id ' + id)); 15 | }); 16 | 17 | router.route('/').get(function (req, res) { 18 | res.send('hello!'); 19 | }); 20 | 21 | router.route('/user/:user').get(function (req, res) { 22 | res.send('User with id ' + req.param('id') + ': ' + req.user); 23 | }); 24 | 25 | app.use(logger({ 26 | name: 'logger', 27 | streams: [/*{ 28 | level: 'info', 29 | stream: process.stdout 30 | }, */{ 31 | level: 'info', 32 | stream: fs.createWriteStream('express.log') 33 | }] 34 | })); 35 | 36 | app.use('/static', express.static(__dirname + '/data')); 37 | app.use('/api/', router); 38 | 39 | app.listen(12345, function () { 40 | console.log('Listening on port 12345'); 41 | }); 42 | -------------------------------------------------------------------------------- /src/05-Working_with_the_Process_API/README.md: -------------------------------------------------------------------------------- 1 | node-certification 2 | ================== 3 | 4 | SCND Strongloop Certification Exam work out 5 | 6 | # Working with the Process API 7 | 8 | The [process](https://nodejs.org/docs/latest-v0.12.x/api/process.html) object is a global object and can be accessed from anywhere. 9 | For the purposes of the exam you should understand signal events, accessing environmental variables and dealing with child processes. 10 | 11 | ## Content 12 | 13 | * ./process.js 14 | 15 | ## License 16 | [Read the LICENSE file (MIT, anyway)](../../LICENSE) 17 | 18 | ## Reference 19 | [http://strongloop.com/node-js/certification/scnd-study-guide/](http://strongloop.com/node-js/certification/scnd-study-guide/) 20 | -------------------------------------------------------------------------------- /src/05-Working_with_the_Process_API/process.js: -------------------------------------------------------------------------------- 1 | var util = require('util'); 2 | 3 | process.on('exit', function (code) { 4 | console.log('bye bye with code ' + code); 5 | 6 | setTimeout(function () { 7 | console.log('This code won\'t execute :('); 8 | }, 1000); 9 | 10 | console.log('Mario!'); 11 | }); 12 | 13 | var sigintCounter = 0; 14 | process.on('SIGINT', function () { 15 | console.log('CTRL+C intercepted, phuqer!'); 16 | 17 | if (sigintCounter > 1) { 18 | process.kill(); 19 | } 20 | 21 | sigintCounter++; 22 | }); 23 | 24 | setTimeout(function () { 25 | console.log('This need to continue the process execution for 10 seconds'); 26 | }, 10000); 27 | 28 | process.stderr.write('DUUUUDE, an error!'); 29 | process.stdout.write('Dude, outputting!' + "\n"); 30 | 31 | process.stdin.on('readable', function () { 32 | var chunk = process.stdin.read(); 33 | 34 | if (chunk !== null) { 35 | switch (chunk.slice(0, chunk.length - 1).toString()) { 36 | case 'argv': 37 | process.stdout.write('argv > '); 38 | process.stdout.write(util.inspect(process.argv)); 39 | process.stdout.write("\n"); 40 | break; 41 | case 'kill': 42 | process.stdout.write('Killing myself'); 43 | process.kill(); 44 | break; 45 | case 'memory': 46 | process.stdout.write('Memory usage > '); 47 | process.stdout.write(util.inspect(process.memoryUsage())); 48 | process.stdout.write("\n"); 49 | break; 50 | case 'info': 51 | process.stdout.write('Info > '); 52 | process.stdout.write('Arch: ' + process.arch + "\n"); 53 | process.stdout.write('Title: ' + process.title + "\n"); 54 | process.stdout.write('Platform: ' + process.platform + "\n"); 55 | process.stdout.write('Version: ' + process.version + "\n"); 56 | process.stdout.write('Lib versions: \n'); 57 | process.stdout.write(util.inspect(process.versions) + "\n"); 58 | break; 59 | default: 60 | process.stdout.write('Unknown command > ' + chunk); 61 | } 62 | } 63 | }); 64 | 65 | process.stdin.on('end', function () { 66 | process.stdout.write('end'); 67 | }); -------------------------------------------------------------------------------- /src/06-Error_Handling/README.md: -------------------------------------------------------------------------------- 1 | node-certification 2 | ================== 3 | 4 | SCND Strongloop Certification Exam work out 5 | 6 | # Error Handling 7 | 8 | Error handling in Node can be tricky so it’s import to understand how to do proper error handling. 9 | 10 | The exam will test your understanding of: 11 | * [Domains](https://nodejs.org/docs/latest-v0.12.x/api/domain.html): Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an error event, or throw an error, then the domain object will be notified, rather than losing the context of the error or causing the program to exit immediately. 12 | * [Exceptions](http://www.nodewiz.biz/nodejs-error-handling-pattern): In Node, errors can occur either explicitly, implicitly, on an error event or as a callback argument. 13 | * [Error objects](http://strongloop.com/strongblog/robust-node-applications-error-handling/): The error object is a built-in object that provides a standard set of useful information when an error occurs, such as a stack trace and the error message. 14 | 15 | Adam Crabtree of Linkedin has done an excellent presentation on the fundamentals of control flow and error handling. 16 | You can watch his [presentation here](http://strongloop.com/developers/videos/#Node-js-Asynchrony-Control-flow-and-Error-handling-with-Adam-Crabtree). 17 | 18 | ## Content 19 | 20 | * ./errors.js 21 | * ./domain.js 22 | 23 | ## License 24 | [Read the LICENSE file (MIT, anyway)](../../LICENSE) 25 | 26 | ## Reference 27 | [http://strongloop.com/node-js/certification/scnd-study-guide/](http://strongloop.com/node-js/certification/scnd-study-guide/) 28 | -------------------------------------------------------------------------------- /src/06-Error_Handling/domain.js: -------------------------------------------------------------------------------- 1 | var domain = require('domain'); 2 | 3 | function domainErrorHandler (err) { 4 | console.log('Raised an error and catched from master domain: ' + err.message); 5 | console.error('error', err.stack); 6 | 7 | console.log('Setting up a killer timer to force the exit of the process, even if there are other running async functions!'); 8 | var killerTimer = setTimeout(function () { 9 | console.log('Forcing process to exit!'); 10 | process.exit(); 11 | }, 8000); 12 | // Don't keep the process open for the killertimer 13 | killerTimer.unref(); 14 | 15 | console.log('Wait the end of the process until the async function is done'); 16 | setTimeout(function () { 17 | console.log('Now exit!'); 18 | }, 10000); 19 | } 20 | 21 | function subdomainErrorHandler (err) { 22 | console.log('Raised an error and catched from subdomain: ' + err.message); 23 | console.error('error', err.stack); 24 | 25 | console.log('Setting up a killer timer to force the exit of the process, even if there are other running async functions!'); 26 | var killerTimer = setTimeout(function () { 27 | console.log('Forcing process to exit!'); 28 | process.exit(); 29 | }, 8000); 30 | // Don't keep the process open for the killertimer 31 | killerTimer.unref(); 32 | 33 | console.log('Wait the end of the process until the async function is done'); 34 | setTimeout(function () { 35 | console.log('Now exit!'); 36 | }, 10000); 37 | } 38 | 39 | var d1 = domain.create(); 40 | d1.on('error', domainErrorHandler); 41 | 42 | d1.run(function () { 43 | console.log('DomainTask started!'); 44 | console.log('Simulating an error in 5 secs!'); 45 | 46 | setTimeout(function () { 47 | lol(); 48 | }, 5000); 49 | 50 | var d2 = domain.create(); 51 | 52 | d2.on('error', subdomainErrorHandler); 53 | d2.run(function () { 54 | console.log('SubDomainTask started!'); 55 | console.log('Simulating an error in 2 secs!'); 56 | 57 | setTimeout(function () { 58 | lol(); 59 | }, 2000); 60 | }); 61 | }); -------------------------------------------------------------------------------- /src/06-Error_Handling/errors.js: -------------------------------------------------------------------------------- 1 | try { 2 | throw new Error('Caught error'); 3 | } 4 | catch (err) { 5 | console.dir(err); 6 | } 7 | 8 | try { 9 | var thrower = function () { 10 | throw new Error('Caugth error#2'); 11 | }; 12 | 13 | thrower(); 14 | } 15 | catch (err) { 16 | console.error(err); 17 | } 18 | 19 | try { 20 | var thrower = function () { 21 | //throw new Error('Uncaught error'); 22 | }; 23 | 24 | process.nextTick(thrower) 25 | } 26 | catch (err) { 27 | console.error(err); 28 | } 29 | 30 | try { 31 | var thrower = function () { 32 | throw new Error('Caught error#3'); 33 | }; 34 | 35 | process.nextTick(function () { 36 | try { 37 | thrower(); 38 | } 39 | catch (err) { 40 | console.error(err); 41 | } 42 | }); 43 | 44 | thrower(); 45 | } 46 | catch (err) { 47 | console.error(err); 48 | } 49 | 50 | var async = require('async'); 51 | 52 | async.waterfall([ 53 | function (cb) { 54 | //throw new Error('Uncaught error#2'); 55 | cb(); 56 | }, 57 | function (cb) { 58 | try { 59 | throw new Error('Caught error#4'); 60 | } 61 | catch (err) { 62 | cb(err); 63 | } 64 | } 65 | ], function (err, result) { 66 | if (err) console.error(err); 67 | else console.log(result); 68 | }); 69 | 70 | var q = require('q'); 71 | 72 | function first () { 73 | var dfd = q.defer(); 74 | 75 | process.nextTick(function () { 76 | try { 77 | throw new Error('promise error'); 78 | } 79 | catch (err) { 80 | dfd.reject(err); 81 | } 82 | }); 83 | 84 | return dfd.promise; 85 | } 86 | 87 | function second () { 88 | var dfd = q.defer(); 89 | 90 | process.nextTick(function () { 91 | throw new Error('promise error'); 92 | }); 93 | 94 | return dfd.promise; 95 | } 96 | 97 | function third () { 98 | var dfd = q.defer(); 99 | 100 | process.nextTick(function () { 101 | throw new Error('promise error'); 102 | }); 103 | 104 | return dfd.promise; 105 | } 106 | 107 | first() 108 | .then(second) 109 | .then(third) 110 | .then(function () { 111 | 112 | }, function (err) { 113 | console.error(err); 114 | }); -------------------------------------------------------------------------------- /src/07-Sockets/README.md: -------------------------------------------------------------------------------- 1 | node-certification 2 | ================== 3 | 4 | SCND Strongloop Certification Exam work out 5 | 6 | # Sockets 7 | 8 | [WebSockets](http://strongloop.com/strongblog/real-time-engines-in-node-js/) in Node commonly manifest themselves when developers make use of the [socket.io](http://socket.io) framework. 9 | [WebSockets](http://strongloop.com/strongblog/real-time-engines-in-node-js/) is a protocol providing full-duplex communications channels over a single TCP connection. 10 | For the purposes of the exam, you should have a basic understanding of how [WebSockets](http://strongloop.com/strongblog/real-time-engines-in-node-js/) work, why they are advantageous in Node and how they can be integrated into your application with the [socket.io](http://socket.io) framework. 11 | 12 | ## Content 13 | 14 | * ./websocket.js 15 | * ./websocket.html 16 | 17 | ## License 18 | [Read the LICENSE file (MIT, anyway)](../../LICENSE) 19 | 20 | ## Reference 21 | [http://strongloop.com/node-js/certification/scnd-study-guide/](http://strongloop.com/node-js/certification/scnd-study-guide/) 22 | -------------------------------------------------------------------------------- /src/07-Sockets/websocket.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | WebSockets Demo 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 23 | 24 | 25 |
26 | 27 | 30 | 31 |
32 | 33 |
34 | 35 |
36 | 37 | 38 |
39 | 40 | 41 |
42 | 43 |
44 |
45 | 46 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /src/07-Sockets/websocket.js: -------------------------------------------------------------------------------- 1 | var io = require('socket.io')(12345); 2 | 3 | io.on('connection', function (socket) { 4 | 5 | console.log('A socket has connected'); 6 | 7 | socket.on('ping', function (data) { 8 | console.log('Intercepted event: ping'); 9 | console.log('Data is: '); 10 | console.dir(data); 11 | 12 | socket.emit('pong', data); 13 | }); 14 | 15 | socket.on('broadcast', function (data) { 16 | console.log('Intercepted event: broadcast'); 17 | console.log('Data is: '); 18 | console.dir(data); 19 | socket.broadcast.emit('message', data); 20 | }); 21 | 22 | socket.on('all', function (data) { 23 | console.log('Intercepted event: all'); 24 | console.log('Data is: '); 25 | console.dir(data); 26 | io.sockets.emit('message', data); 27 | }); 28 | 29 | socket.on('disconnect', function () { 30 | console.log('SOCKET DISCONNECTED'); 31 | }); 32 | 33 | setInterval(function() { 34 | console.log("Broadcasting time"); 35 | socket.broadcast.emit('message', new Date()); 36 | }, 3000); 37 | 38 | }); 39 | 40 | console.log('WSS Server listening on 12345'); 41 | -------------------------------------------------------------------------------- /src/08-Clustering_and_Multi-Process/README.md: -------------------------------------------------------------------------------- 1 | node-certification 2 | ================== 3 | 4 | SCND Strongloop Certification Exam work out 5 | 6 | # Clustering and MultiProcess 7 | 8 | Before deploying a Node app, it’s important to understand what your options are for scalability not just around performance, but also for uptime. 9 | 10 | For the purposes of the exam you should have a general understanding of how Node’s [Cluster API](https://nodejs.org/docs/latest-v0.12.x/api/cluster.html) works and how it might be leveraged to create scalable applications. 11 | 12 | ## Content 13 | 14 | * ./cluster.js 15 | * ./workers/worker1.js 16 | * ./cluster-domain.js 17 | * ./workers/domain-worker.js 18 | 19 | ## License 20 | [Read the LICENSE file (MIT, anyway)](../../LICENSE) 21 | 22 | ## Reference 23 | [http://strongloop.com/node-js/certification/scnd-study-guide/](http://strongloop.com/node-js/certification/scnd-study-guide/) 24 | -------------------------------------------------------------------------------- /src/08-Clustering_and_Multi-Process/cluster-domain.js: -------------------------------------------------------------------------------- 1 | var cluster = require('cluster'), 2 | cpus = require('os').cpus().length; 3 | 4 | cluster.setupMaster({ 5 | exec: __dirname + '/workers/domain-worker.js' 6 | }); 7 | 8 | for (var i = 0; i < cpus; i++) cluster.fork(); 9 | 10 | cluster.on('disconnect', function (worker) { 11 | console.log('Worker disconnected. Forking again'); 12 | cluster.fork(); 13 | }); -------------------------------------------------------------------------------- /src/08-Clustering_and_Multi-Process/cluster.js: -------------------------------------------------------------------------------- 1 | var cluster = require('cluster'), 2 | cpus = require('os').cpus().length, 3 | clusterPrefix = '[Cluster] -> '; 4 | 5 | function onClusterDisconnect (worker) { 6 | console.log(clusterPrefix + 'a worker with PID ' + worker.process.pid + ' has been disconnected'); 7 | } 8 | 9 | function onClusterExit (worker, code, signal) { 10 | var signalMessage = signal ? ' and with signal ' + signal : ''; 11 | console.log(clusterPrefix + 'a worker with PID ' + worker.process.pid + ' has been exited with code ' + code + signalMessage); 12 | 13 | cpus--; 14 | 15 | if (cpus === 0) { 16 | console.log(clusterPrefix + 'no more worker available. Exiting.'); 17 | process.exit(0); 18 | } 19 | } 20 | 21 | function onClusterFork (worker) { 22 | console.log(clusterPrefix + 'a new worker has been forked with PID ' + worker.process.pid); 23 | } 24 | 25 | function onClusterOnline (worker) { 26 | console.log(clusterPrefix + 'a new worker is online with PID ' + worker.process.pid); 27 | 28 | //worker.send('Hi worker! Welcome to the virtual world!'); 29 | 30 | worker.send({ 31 | event: 'hello', 32 | message: 'Hi worker! Welcome to the virtual world!' 33 | }); 34 | 35 | worker.on('message', onClusterMessage); 36 | } 37 | 38 | function onClusterListening (worker, addressInfo) { 39 | console.log(clusterPrefix + 'listening on a worker PID ' + worker.process.pid + ', @ ' + addressInfo.address + ', port: ' + addressInfo.port + ', type: ' + addressInfo.addressType); 40 | } 41 | 42 | function onClusterSetup () { 43 | console.log(clusterPrefix + 'setup a worker'); 44 | } 45 | 46 | function onClusterMessage (msg) { 47 | if (typeof msg === 'object') { 48 | console.log(clusterPrefix + 'Event: ' + msg.event + '; SenderId: ' + msg.senderId); 49 | } 50 | else { 51 | console.log(clusterPrefix + 'incoming message from worker:'); 52 | console.log('Cluster >> ' + msg); 53 | } 54 | } 55 | 56 | if (cluster.isMaster) { 57 | cluster.on('disconnect', onClusterDisconnect); 58 | cluster.on('exit', onClusterExit); 59 | cluster.on('fork', onClusterFork); 60 | cluster.on('online', onClusterOnline); 61 | cluster.on('setup', onClusterSetup); 62 | cluster.on('listening', onClusterListening); 63 | 64 | // This let to move a worker code from the main master file to a different one (the worker file) 65 | console.log(clusterPrefix + 'setup Master to fork workers in an external file'); 66 | cluster.setupMaster({ 67 | exec: __dirname + '/workers/worker1.js', 68 | args: ['--use', 'https'], 69 | silent: false 70 | }); 71 | 72 | for (var i = 0; i < cpus; i++) { 73 | console.log(clusterPrefix + 'spawning a new process'); 74 | cluster.fork(); 75 | } 76 | 77 | setTimeout(function () { 78 | for (var wid in cluster.workers) { 79 | var worker = cluster.workers[wid]; 80 | 81 | worker.send('shutdown'); 82 | worker.disconnect(); 83 | } 84 | }, 6000); 85 | 86 | setTimeout(function () { 87 | cluster.disconnect(); 88 | }, 12000); 89 | } 90 | else { 91 | /*console.log('Worker: new process spawned with PID ' + process.pid); 92 | 93 | setTimeout(function () { 94 | cluster.worker.disconnect(); 95 | }, Math.random() * 5000); 96 | 97 | setTimeout(function () { 98 | cluster.worker.kill(); 99 | }, Math.random() * 5000);*/ 100 | } -------------------------------------------------------------------------------- /src/08-Clustering_and_Multi-Process/workers/domain-worker.js: -------------------------------------------------------------------------------- 1 | var cluster = require('cluster'), 2 | domain = require('domain'), 3 | masterDomain = domain.create(); 4 | 5 | /*masterDomain.on('error', function (err) { 6 | console.error('Error: ', err.stack); 7 | 8 | try { 9 | // Disconnecting domain 10 | cluster.worker.disconnect(); 11 | } 12 | catch (err) { 13 | console.error('Error', err.stack); 14 | } 15 | });*/ 16 | 17 | masterDomain.run(function () { 18 | var express = require('express'), 19 | router = express.Router(), 20 | app = express(); 21 | 22 | app.use(function (req, res, next) { 23 | masterDomain.add(req); 24 | masterDomain.add(res); 25 | masterDomain.on('error', next); 26 | }); 27 | 28 | router.route('/').get(function (req, res, next) { 29 | console.log('GET /'); 30 | console.log('Responding with "Hello world!"'); 31 | 32 | // Throw an expection 33 | //lol(); 34 | 35 | process.nextTick(function () { 36 | throw new Error('Uncaught exception!'); 37 | }); 38 | 39 | //res.status(200).send('Hello world!'); 40 | }); 41 | 42 | app.use('/api/', router); 43 | // Error handler 44 | app.use(function (err, req, res, next) { 45 | console.error('Error', err.stack); 46 | 47 | try { 48 | console.log('Closing web server and disconnecting worker'); 49 | server.close(); 50 | cluster.worker.disconnect(); 51 | 52 | res.status(500).send(err.message); 53 | } 54 | catch (err) { 55 | console.error('Error', err.stack); 56 | } 57 | }); 58 | 59 | var server = app.listen(12345, function () { 60 | console.log('HTTP Server listening on port 12345'); 61 | }); 62 | }); -------------------------------------------------------------------------------- /src/08-Clustering_and_Multi-Process/workers/worker1.js: -------------------------------------------------------------------------------- 1 | var cluster = require('cluster'), 2 | workerPrefix = '[Worker#' + process.pid + ']: '; 3 | 4 | function onWorkerMessage (msg) { 5 | if (typeof msg === 'object') { 6 | console.log(workerPrefix + 'Event: ' + msg.event + '; Message: ' + msg.message); 7 | 8 | cluster.worker.send({ 9 | event: 'hello', 10 | senderId: process.pid 11 | }); 12 | } 13 | else { 14 | if (msg === 'shutdown') { 15 | console.log(workerPrefix + 'Shutting down gracefully...'); 16 | } 17 | else { 18 | console.log(workerPrefix + 'a new message incoming from Master:'); 19 | console.log('Worker >> ' + msg); 20 | 21 | cluster.worker.send('Hello from Worker#' + process.pid); 22 | } 23 | } 24 | } 25 | 26 | function onWorkerOnline () { 27 | console.log(workerPrefix + 'I\'m online with PID ' + process.pid); 28 | } 29 | 30 | function onWorkerDisconnect () { 31 | console.log(workerPrefix + 'has disconnected'); 32 | } 33 | 34 | function onWorkerExit (code, signal) { 35 | var signalMessage = signal ? ' and with signal ' + signal : ''; 36 | console.log(workerPrefix + 'has exited with code: ' + code + signalMessage); 37 | } 38 | 39 | function onWorkerError (err) { 40 | console.log(workerPrefix + 'something going wrong:'); 41 | console.dir(err); 42 | } 43 | 44 | 45 | cluster.worker.on('message', onWorkerMessage); 46 | cluster.worker.on('online', onWorkerOnline); 47 | cluster.worker.on('disconnect', onWorkerDisconnect); 48 | cluster.worker.on('exit', onWorkerExit); 49 | cluster.worker.on('error', onWorkerError); 50 | 51 | console.log(workerPrefix + 'new process spawned with PID ' + process.pid); 52 | 53 | /*setTimeout(function () { 54 | cluster.worker.disconnect(); 55 | }, Math.random() * 5000); 56 | 57 | setTimeout(function () { 58 | cluster.worker.kill(); 59 | }, Math.random() * 5000);*/ -------------------------------------------------------------------------------- /src/09-Deployment/README.md: -------------------------------------------------------------------------------- 1 | node-certification 2 | ================== 3 | 4 | SCND Strongloop Certification Exam work out 5 | 6 | # Deployment 7 | 8 | For the purposes of the exam it it’s import to understand some of the fundamental tasks you’ll need to preform in the application deployment process. 9 | 10 | For example high-availability, clustering in multi-core environments, zero downtime deployments and log rotation. Qasim Zaidi has put together an excellent [“Node in production”](http://qzaidi.github.io/2013/05/14/node-in-production/) post on these topics. 11 | 12 | ## Content 13 | 14 | No files by the moment sorry :( 15 | To contrib use [pull requests](https://help.github.com/articles/using-pull-requests). 16 | 17 | ## License 18 | [Read the LICENSE file (MIT, anyway)](../../LICENSE) 19 | 20 | ## Reference 21 | [http://strongloop.com/node-js/certification/scnd-study-guide/](http://strongloop.com/node-js/certification/scnd-study-guide/) 22 | -------------------------------------------------------------------------------- /src/10-Troubleshooting/README.md: -------------------------------------------------------------------------------- 1 | node-certification 2 | ================== 3 | 4 | SCND Strongloop Certification Exam work out 5 | 6 | # Troubleshooting 7 | 8 | It is important for Node developers to have an understanding of what development tools are at their disposal and how to leverage them. For the purposes of the exam, you should have a general understanding of the following tools: 9 | 10 | * Debugging: Understanding the built in [debugger](https://nodejs.org/docs/latest-v0.12.x/api/debugger.html) and [Node inspector]() 11 | * Memory leak detection: [Using event listeners](https://nodejs.org/docs/latest-v0.12.x/api/events.html) to catch memory leaks 12 | * [Using REPL](https://nodejs.org/docs/latest-v0.12.x/api/repl.html): A Read-Eval-Print-Loop (REPL) is available both as a standalone program and easily includable in other programs. The REPL provides a way to interactively run JavaScript and see the results. It can be used for debugging, testing, or just trying things out. 13 | 14 | ## Content 15 | 16 | * ./repl.js 17 | 18 | ## License 19 | [Read the LICENSE file (MIT, anyway)](./../LICENSE) 20 | 21 | ## Reference 22 | [http://strongloop.com/node-js/certification/scnd-study-guide/](http://strongloop.com/node-js/certification/scnd-study-guide/) 23 | -------------------------------------------------------------------------------- /src/10-Troubleshooting/repl.js: -------------------------------------------------------------------------------- 1 | var repl = require('repl'), 2 | net = require('net'); 3 | 4 | module.exports = net.createServer(function (socket) { 5 | console.log('Server started'); 6 | var r = repl.start({ 7 | prompt: ['[', process.pid, '] - ', socket.remoteAddress, ':', socket.remotePort, ' > '].join(''), 8 | input: socket, 9 | output: socket 10 | }).on('exit', function () { 11 | socket.end(); 12 | }); 13 | }).listen(1337, function () { 14 | console.log('TCP Server listening on 1337'); 15 | }); -------------------------------------------------------------------------------- /utils.js: -------------------------------------------------------------------------------- 1 | // Using: http://stackoverflow.com/questions/22646996/how-do-i-run-a-node-js-script-from-within-another-node-js-script 2 | 3 | 'use strict'; 4 | 5 | var childProcess = require('child_process'); 6 | 7 | module.exports = { 8 | 9 | runScript : function (scriptPath, pointers, callback) { 10 | 11 | var self = this; 12 | 13 | // Clean previous executions (like express); 14 | for (var i in pointers) { 15 | pointers[i].shutdown(); 16 | 17 | } 18 | 19 | pointers = []; 20 | 21 | // keep track of whether callback has been invoked to prevent multiple invocations 22 | var invoked = false; 23 | var process = childProcess.fork(scriptPath); 24 | pointers.push(process); 25 | 26 | // Function to propagate errors 27 | process.callbackError = function (code) { 28 | 29 | if (invoked) { return } 30 | invoked = true; 31 | 32 | var err = code === 0 ? null : new Error('exit code ' + code); 33 | self.callback(err); 34 | }; 35 | 36 | // Own kill function, remove listener and kill itself 37 | process.shutdown = function () { 38 | // Get rid of the exit listener since this is a planned exit. 39 | this.removeListener("exit", this.callbackError); 40 | this.kill("SIGTERM"); 41 | }; 42 | 43 | // execute the callback once the process has finished running 44 | process.on('exit', process.callbackError); 45 | 46 | // listen for errors as they may prevent the exit event from firing 47 | process.on('error',function (err) { 48 | 49 | if (invoked) { return } 50 | invoked = true; 51 | 52 | callback(err); 53 | }); 54 | 55 | return pointers; 56 | }, 57 | 58 | callback: function (err) { 59 | 60 | if (err) { 61 | console.log('Error running script'); 62 | console.log(err); 63 | } 64 | 65 | console.log('Pres any key to go back to menu'); 66 | } 67 | }; --------------------------------------------------------------------------------