Thứ Năm, 15 tháng 4, 2021

Xóa đi tất cả các node process


Cấu hình Nodemon trong NodeJS



Nodemon sẽ luôn theo dõi sự thay đổi của các files trong thư mục,
nếu có bất kì thay đổi nào trong file nó sẽ build lại ứng dụng
==> rất thích hợp để chạy trên môi trường dev,
cần xem sự thay đổi ngay khi chỉnh sửa source code.

https://github.com/remy/nodemon
## Installation > npm install -g nodemon

## Set specific extensions
nodemon -e js,mjs,json,ejs src/index.js

## Monitoring multiple directories
nodemon --watch app --watch libs app/server.js

## Ignoring files
nodemon --ignore lib/ --ignore tests/
nodemon --ignore lib/app.js
nodemon --ignore 'lib/*.js'

## Application isn't restarting
Trong một số môi trường nodemon không thể chạy được, cần bổ sung `legacyWatch: true`.
nodemon -L


Xử lý đa luồng trong NodeJS




Trong một vài trường hợp một số xử lý rất tốn tài nguyên và mất rất nhiều thời gian để xử lý.

db.findAll('SELECT ...', function(err, results) {
if (err) return console.error(err)
// Heavy computation and many results
for (const encrypted of results) {
const plainText = decrypt(encrypted)
console.log(plainText)
}
})

Node JS luôn chỉ mở một thread để handle all request.
Nên nếu một xử lý quá nặng và mất thời gian, có thể làm đóng băng cả hệ thống.
==> Các xử lý đều cần phải xử lý bất đồng bộ, để không bị mắc kẹt ở một event nào.

#### Cách 1: chia nhỏ một event có xử lý quá nặng thành các phần nhỏ.
Xử lý từng phần ở hàng đợi
mỗi lần xử lý 10 item và gọi `setImmediate(callback)`
vì vậy nếu có việc gì khác mà chương trình cần phải làm,
nó sẽ được thực hiện chen giữa các khối 10 item.

const crypto = require('crypto')

const arr = new Array(200).fill('something')
function processChunk() {
if (arr.length === 0) {
// code that runs after the whole array is executed
} else {
console.log('processing chunk');
// pick 10 items and remove them from the array
const subarr = arr.splice(0, 10)
for (const item of subarr) {
// do heavy stuff for each item on the array
doHeavyStuff(item)
}
// Đưa function xử lý vào lại hàng đợi
setImmediate(processChunk)
}
}

processChunk()

function doHeavyStuff(item) {
crypto.createHmac('sha256', 'secret')
            .update(new Array(10000).fill(item).join('.')).digest('hex')
}

// This is just for confirming that we can continue
// doing things
let interval = setInterval(() => {
console.log('tick!')
if (arr.length === 0) clearInterval(interval)
}, 0)

Tuy nhiên cách này dữ liệu được chia nhỏ xử lý từng phần
và sẽ bị chen ngang rất nhiều lần dẫn đến thời gian để người gửi request nhận
được kết quả là rất lâu.

#### Cách 2: Dùng fork process (background process) - worker-farm module
Đưa function xử lý nặng vào file script.js.
Khởi chạy một task với input, mà có thể sử dụng bất cứ lượng CPU nào và thời gian nó cần,
và sau đó trả lại kết quả cho main app.

// main app
const workerFarm = require('worker-farm')

// Tạo 1 worker xử lý riêng ở script.js
const service = workerFarm(require.resolve('./script'))
service('hello', function (err, output) {
console.log(output)
})

// script.js
// This will run in forked processes
module.exports = (input, callback) => {
callback(null, input + ' ' + world)
}

Vấn đề được giải quyết, nhưng ta vẫn sử dụng rất nhiều bộ nhớ hơn thay vì multithreading.
Thread vẫn rất là gọn nhẹ so với forked process.
Và đây là lý do `Worker Thread` được sinh ra.

#### Cách 3: sử dụng Worker Thread
https://nodejs.org/api/worker_threads.html

// File index.js : run with `node --experimental-worker index.js` on Node.js 10.x

// import worker_threads module
const { Worker } = require('worker_threads')

// khởi tạo worker từ file service.js,
    // truyền dữ liệu vào và chờ kết quả sau khi service.js xử lý xong
function runService(workerData) {
return new Promise((resolve, reject) => {
// tạo mới worker từ file service.js
const worker = new Worker('./service.js', { workerData });

worker.on('message', resolve);
worker.on('error', reject);
worker.on('exit', (code) => {
if (code !== 0)
reject(new Error(`Worker stopped with exit code ${code}`));
})
})
}

// tạo function bất đồng bộ để xử lý service
async function run() {
const result = await runService('world')
console.log(result);
}

// kích hoạt Worker Thread
run().catch(err => console.error(err))


// File service.js
const { workerData, parentPort } = require('worker_threads')

// You can do any heavy stuff here, in a synchronous way
// without blocking the "main thread"
// Sau khi xử lý xong, gửi message về, kèm theo dữ liệu kết quả.
parentPort.postMessage({ hello: workerData })


Thứ Tư, 14 tháng 4, 2021

Node module phổ biến




## Cheatsheet
https://overapi.com/nodejs

## 2. Module glob
Cho phép duyệt nhanh và lọc các tệp trong một thư mục phức tạp.

glob(pattern, callback);
glob(“img/*”, (err, paths) => {
...
});
// promisified
paths = await glob(“img/*”);

## 3. Module Socket.io
Xây dựng các ứng dụng chat
https://viblo.asia/p/tao-ung-dung-chat-realtime-don-gian-bang-nodejs-gDVK2jJXKLj
https://viblo.asia/p/huong-dan-xay-dung-ung-dung-chat-real-time-voi-node-js-WAyK8peoKxX

## 4. Module multer (handle POST FormData)
Được sử dụng để hỗ trợ các yêu cầu POST FormData ở phía máy chủ,
để có thể truy cập các tham số req.body.

## 5. Mysql Module
Kêt nôis với MYSQL DB: https://www.w3schools.com/nodejs/nodejs_mysql_join.asp

var mysql = require('mysql');

var con = mysql.createConnection({
host: "localhost",
user: "yourusername",
password: "yourpassword",
database: "mydb"
});

con.connect(function(err) {
if (err) throw err;
var sql = "SELECT users.name AS user, products.name AS favorite
            FROM users JOIN products ON users.favorite_product = products.id";
con.query(sql, function (err, result) {
if (err) throw err;
console.log(result);
});
});

## 6. Module promise-mysql
Bọc lại module mysql.
Mỗi function của module mysql sẽ trả về 1 Promise
thay thế cho việc trả về callback ở tham số cuối của function.
Được đề nghị nên sử dụng khi muốn kết nối với mysql.

mysql.createConnection({
host : hostname, // default localhost
port : port,
user : username,
password : pw,
database : dbname
});

db.query(qryString);
db.query(qryString, [placeholders]);

## 7. Mongodb Module
Kết nối với Mongo DB: https://www.w3schools.com/nodejs/nodejs_mongodb_join.asp

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://127.0.0.1:27017/";

MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("mydb");
dbo.collection('orders').aggregate([
{ $lookup:
{
from: 'products',
localField: 'product_id',
foreignField: '_id',
as: 'orderdetails'
}
}
]).toArray(function(err, res) {
if (err) throw err;
console.log(JSON.stringify(res));
db.close();
});
});

## 8. Module cookie-parser
Một mô-đun để truy cập cookie với các đối tượng req / res trong Express.

var express = require('express');
var cookieParser = require('cookie-parser'); // module for parsing cookies
var app = express();
app.use(cookieParser());

app.get('/setcookie', function(req, res){
// setting cookies
res.cookie('username', 'john doe', { maxAge: 900000, httpOnly: true });
return res.send('Cookie has been set');
});

app.get('/getcookie', function(req, res) {
var username = req.cookies['username'];
if (username) {
return res.send(username);
}
return res.send('No cookie found');
});

## Route Functions
- GET
app.get(“path”, middlewareFn(s));
app.get(“/”, (req, res) => {
...
});
app.get(“/:city”, (req, res) => {
let city = req.params.city;
...
});
app.get(“/cityData”, (req, res) => {
let city = req.query.city;
...
});
// Example with multiple middleware functions
app.get(“/”, validateInput, (req, res) => {
...
}, handleErr);

- POST
app.post(“path”, middlewareFn(s));
app.post(“/addItem”, (req, res) => {
let itemName = req.body.name;
...
}

## 9. Request Object Properties/Functions
- req.params Captures a dictionary of desired path parameters.
                    Keys are placeholder names and values are the URL itself.
- req.query Captures a dictionary of query parameters,
                    specified in a ?key1=value1&key2=value2& … pattern.
- req.body Holds a dictionary of POST parameters as key/value pairs.

- req.cookies Retrieves all cookies sent in the request. Requires cookie-parser module.

## 10. Response Object Properties/Functions
- Used to set different response headers - commonly the “Content-type”
res.set(headerName, value);
res.set(“Content-Type”, “text/plain”);
res.set(“Content-Type”, “application/json”);

- Shorthand for setting the “Content-Type” header
res.type(“text”);
res.type(“json”);

- Sends the data back to the client,
signaling an end to the response (does not terminate your JS program).
res.send(data);
res.send(“Hello”);
res.send({ “msg” : “Hello” });

- Ends the request/response cycle without any data
res.end();

- Shorthand for setting the content type to JSON and sending JSON.
res.json(data);

- Specifies the HTTP status code of the response to communicate success/failure to a client.
res.status(statusCode)
res.status(400).send(“client-side error message”);
res.status(500).send(“server-side error message”);

## 11. Events in Node.js
http://nodejs.org/api/events.html
Tất cả mọi hành động xảy ra đều là các events( sự kiện ).

- 1) Các Objects trong Node JS đều có các event đi kèm.

Ví dụ `readStream object` fires events when opening and closing a file
var fs = require('fs');
var rs = fs.createReadStream('./demofile.txt');
rs.on('open', function () {
console.log('The file is open');
});

- 2) `Events Module`
Với module này có thể dễ dàng tự định nghĩa các events.

var events = require('events');
// Tạo mới 1 event
var eventEmitter = new events.EventEmitter();

// Tạo mới 1 event handler
var myEventHandler = function () {
console.log('I hear a scream!');
}

// Đăng kí event handler đến event mới tạo
eventEmitter.on('scream', myEventHandler);

// Kích hoạt event
eventEmitter.emit('scream');


// To access the EventEmitter class, require('events').EventEmitter.
// All EventEmitters emit the event 'newListener'
// when new listeners are added and 'removeListener' when a listener is removed.

// Adds a listener to the end of the listeners array for the specified event.
emitter.addListener(event, listener);
// Same as emitter.addListener().
emitter.on(event, listener);
// Adds a one time listener for the event.
emitter.once(event, listener);
// Remove a listener from the listener array
emitter.removeListener(event, listener);
// Removes all listeners
emitter.removeAllListeners([event]);
emitter.setMaxListeners(n);
// Returns an array of listeners for the specified event.
emitter.listeners(event);
// Execute each of the listeners in order with the supplied arguments.
emitter.emit(event, [arg1], [arg2], [...]);
// Return the number of listeners for a given event.
EventEmitter.listenerCount(emitter, event);

## 12. Node JS Upload Files (Formidable Module)
npm install formidable

var http = require('http');
var formidable = require('formidable');
var fs = require('fs');

http.createServer(function (req, res) {
if (req.url == '/fileupload') {

// nhận các giá trị từ form
var form = new formidable.IncomingForm();

form.parse(req, function (err, fields, files) {
var oldpath = files.filetoupload.path;
var newpath = 'C:/Users/Your Name/' + files.filetoupload.name;
fs.rename(oldpath, newpath, function (err) {
if (err) throw err;
res.write('File uploaded and moved!');
res.end();
});
});
}
else {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('<form action="fileupload" method="post" enctype="multipart/form-data">');
res.write('<input type="file" name="filetoupload"><br>');
res.write('<input type="submit">');
res.write('</form>');
return res.end();
}
}).listen(8080);

## 13. Nodemailer Module (Send Mail)
npm install nodemailer

var nodemailer = require('nodemailer');

var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'youremail@gmail.com',
pass: 'yourpassword'
}
});

var mailOptions = {
from: 'youremail@gmail.com',
to: 'myfriend@yahoo.com', // to: 'myfriend@yahoo.com, myotherfriend@yahoo.com',
subject: 'Sending Email using Node.js',
text: 'That was easy!' // OR html: '<h1>Welcome</h1><p>That was easy!</p>'
};

transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});

## 14. Module Performance Timing API (perf_hooks)
Đo hiệu suất thực hiện một chuỗi các xử lý.

const { readFileSync } = require('fs')
const { performance, PerformanceObserver } = require('perf_hooks')

// triggered whenever a new entry is added to the performance timeline
const obs = new PerformanceObserver(items => {
// give out the new entry of the performance timeline, when added
console.log(items.getEntries())

// to remove the performance marks in the timeline (optional)
performance.clearMarks()
})

// subscribed the PerformanceObserver to new entries of the "measure" type
obs.observe({ entryTypes: ['measure'] })

performance.mark('BigFileStart')
readFileSync('./big.txt')
performance.mark('BigFileEnd')

// measuring from start to end of reading the big file
performance.measure('Big File', 'BigFileStart', 'BigFileEnd')

performance.mark('SmallFileStart')
readFileSync('./small.txt')
performance.mark('SmallFileEnd')

// measuring from start to end of reading the small file
performance.measure('Small File', 'SmallFileStart', 'SmallFileEnd')

## 15. Module Yargs
Yargs là một module có `tác dụng tách chuỗi của các request` và lấy các tham số
+ giá trị của các tham số, module này rất hữu ích trong việc giao tiếp lấy dữ liệu từ client.
npm install yargs

Gọi xử lý: `node yargs-demo.js tmv freetuts`
const yargs = require('yargs');
// Lấy hết tham số
const argv = yargs.argv._;
// In ra xem thử
console.log(argv);

- Truyền theo dạng tham số key-value
node yargs-demo.js --key=value
node yargs-demo.js --domain freetuts.net --author thehalfheart

## 16. Module upper-case
npm install upper-case

var http = require('http');
var uc = require('upper-case');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(uc.upperCase("Hello World!"));
res.end();
}).listen(8080);

## 17. Synopsis (Sơ lược cách vận hành)
// http://nodejs.org/api/synopsis.html

var http = require('http');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World\n');
}).listen(8124);

console.log('Server running at http://127.0.0.1:8124/');

## 18. Global Objects (Một số đối tượng toàn cục sẵn có)
// http://nodejs.org/api/globals.html

__filename; // Đường dẫn tuyệt đối
__dirname; // Thư mục hiện tại của script đang xử lý
module; // Một ánh xạ của module đang được truy xuất.
exports; // Một ánh xạ của module.exports
process; // process object có thể truy xuất từ bất kì đâu. Là 1 instance của EventEmitter.
Buffer; // Buffer class cõ thể truy xuất từ bất kì đâu.


## 19. Console (In giá trị ra màn hình Console)
// http://nodejs.org/api/console.html

console.log([data], [...]); // Prints to stdout with newline.
console.info([data], [...]); // Same as console.log.
console.error([data], [...]); // Same as console.log but prints to stderr.
console.warn([data], [...]); // Same as console.error.
// Uses util.inspect on obj and prints resulting string to stdout.
console.dir(obj);
console.time(label); // Mark a time.
console.timeEnd(label); // Finish timer, record output.
// Print a stack trace to stderr of the current position.
console.trace(label);
// Same as assert.ok() where if the expression evaluates as false
throw an AssertionError with message.
console.assert(expression, [message]);

## 20. Timers
To schedule a execution. Start and stop a timers.
http://nodejs.org/api/timers.html
// To schedule execution of a one-time callback after delay milliseconds.
setTimeout(callback, delay, [arg], [...]);
// Stop a timer that was previously created with setTimeout().
clearTimeout(t);
// To schedule the repeated execution of callback every delay milliseconds
setInterval(callback, delay, [arg], [...]);
// Stop a timer that was previously created with setInterval().
clearInterval(t);
// To schedule the "immediate" execution of callback after I/O events callbacks
setImmediate(callback, [arg], [...]);
// Stop a timer that was previously created with setImmediate().
clearImmediate(immediateObject);

// Allow you to create a timer that is active
// but if it is the only item left in the event loop,
unref();
// If you had previously unref()d a timer you can call ref()
// to explicitly request the timer hold the program open.
ref();


## 21. Modules.
http://nodejs.org/api/modules.html

var module = require('./module.js');
module.require('./another_module.js');

module.id; // The identifier for the module.
module.filename; // The fully resolved filename to the module.
// Whether or not the module is done loading or is in the process of loading.
module.loaded;
module.parent; // The module that required this one.
module.children; // The module objects required by this one.

exports.area = function (r) {
return 3.14 * r * r;
};

// Nếu muốn export một function (như là 1 constructor)
// hoăch là muốn export a complete object thì cần sử dụng module.exports
module.exports = function(width) {
return {
area: function() {
return width * width;
}
};
}

## 22. Process (kiểm soát các tiến trình đang xử lý)
http://nodejs.org/api/process.html
Process object có thể truy cập từ bất kì đâu,
để kiểm soát các tiến trình mà Node JS đang xử lý

## 23. Child Process (tạo ra các xử lý con)
Mô-đun `ChildProcess` cung cấp khả năng sinh ra các quy trình con

// Node provides a tri-directional popen facility through the child_process module.
// It is possible to stream data through a child's stdin, stdout,
// and stderr in a fully non-blocking way.
http://nodejs.org/api/child_process.html

ChildProcess;

child.stdin;
child.stdout;
child.stderr;
child.pid;
child.connected;
child.kill([signal]);
child.send(message, [sendHandle]);
child.disconnect();
child_process.spawn(command, [args], [options]);
child_process.exec(command, [options], callback);
child_process.execFile(file, [args], [options], [callback]);
child_process.fork(modulePath, [args], [options]);

## 24. Module Util (Một số function tiện ích được viết sẵn)
// http://nodejs.org/api/util.html

util.format(format, [...]);
util.debug(string);
util.error([...]);
util.puts([...]);
util.print([...]);
util.log(string);
util.inspect(object, [opts]);
util.isArray(object);
util.isRegExp(object);
util.isDate(object);
util.isError(object);

// Inherit the prototype methods from one constructor into another.
util.inherits(constructor, superConstructor);


## 25. Stream (Xử lý đọc và ghi một luồng dữ liệu)
http://nodejs.org/api/stream.html

## 26. File System. (Module fs - Xử lý đọc, ghi, đổi tên, phân quyền, xóa một file hệ thống)
http://nodejs.org/api/fs.html
Module fs - Xử lý đọc, ghi, đổi tên, phân quyền, xóa một file hệ thống. Kiểm tra 1 thư mục,
đọc tất cả các file trong 1 thư mục..

const fs = require(‘fs’)

- Kiểm tra xem đường dẫn có phải là một thư mục: `fs.statSync(‘./index.html’).isDirectory()`

- Duyệt qua các file trong 1 thư mục:
fs.readdir(‘./test-dir’, (err, files) => {
files.forEach(file => {
console.log(file)
})
})

- Xem tình trạng file:
fs.watch(‘./test-dir’, (eventType, filename) => {
if (filename) console.log(filename, eventType)
})

- Tạo mới file và ghi file
fs.open('mynewfile2.txt', 'w', function (err, file) {
if (err) throw err;
console.log('Saved!');
});

- Đọc file
fs.readFile(‘./note.txt’, ‘utf8’, (err, data) => {
console.log(data)
})

// Trả về HTML content
fs.readFile('demofile1.html', function(err, data) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(data);
return res.end();
});

- Ghi thêm dữ liệu vào file
fs.appendFile(‘./note.txt’, ‘This is new!’, err => {
if (err) throw err
console.log(‘file changed’)
})

- Ghi đè lên dữ liệu cũ
fs.writeFile(‘./note.txt’, ‘’, err => {
if (err) throw err
console.log(‘file cleared’)
})

- Xóa File
fs.unlink('mynewfile2.txt', function (err) {
if (err) throw err;
console.log('File deleted!');
});

- Rename
fs.rename('mynewfile1.txt', 'myrenamedfile.txt', function (err) {
if (err) throw err;
console.log('File Renamed!');
});

## 27. Path (Module Path - Lấy ra đường dẫn, tạo đường dẫn, lấy ra extension file..)
https://nodejs.org/api/path.html

var fs = require('path')
path.normalize(p);
path.join([path1], [path2], [...]);
path.resolve([from ...], to);
path.relative(from, to);
path.dirname(p);
path.basename(p, [ext]);

path.extname(p);

path.sep;
path.delimiter;


## 28. HTTP (kiểm soát các request vào và trả về các response data)
// http://nodejs.org/api/http.html

var httpServer = require('http')
http.STATUS_CODES;
http.request(options, [callback]);
http.get(options, [callback]);

server = http.createServer([requestListener]);
server.listen(port, [hostname], [backlog], [callback]);
server.listen(path, [callback]);
server.listen(handle, [callback]);
server.close([callback]);
server.setTimeout(msecs, callback);

server.maxHeadersCount;
server.timeout;

server.on('request', function (request, response) { });
server.on('connection', function (socket) { });
server.on('close', function () { });
server.on('checkContinue', function (request, response) { });
server.on('connect', function (request, socket, head) { });
server.on('upgrade', function (request, socket, head) { });
server.on('clientError', function (exception, socket) { });

## 29. URL (cung cấp cac tiện ích để tạo và phân tách 1 URL)
http://nodejs.org/api/url.html

url.parse(urlStr, [parseQueryString], [slashesDenoteHost]);
url.format(urlObj);
url.resolve(from, to);

---------
const url = require("url")
url.parse(‘https://medium.com/@louispetrik')

==> Result:
Url {
protocol: ‘https:’,
slashes: true,
auth: null,
host: ‘medium.com’,
port: null,
hostname: ‘medium.com’,
hash: null,
search: null,
query: null, // //returns an object: { year: 2017, month: 'february' }
pathname: ‘/@louispetrik’,
path: ‘/@louispetrik’,
href: ‘https://medium.com/@louispetrik'
}

## 30. Query String (Chuyển 1 object thành 1 chuỗi các tham số nối nhau bởi & và ngược lại)
http://nodejs.org/api/querystring.html

var querystring = require('querystring')

// Serialize an object to a query string.
// Optionally override the default separator ('&') and assignment ('=') characters.
querystring.stringify(obj, [sep], [eq]);

// Deserialize a query string to an object.
// Optionally override the default separator ('&') and assignment ('=') characters.
querystring.parse(str, [sep], [eq], [options]);


## 31. Assert (Dùng để viết unit test)
http://nodejs.org/api/assert.html

## 32. OS
Module này có thể xuất ra tất cả các loại thông tin về hệ thống mà NodeJS hiện đang chạy.
Ví dụ, nó có thể được sử dụng để giám sát hoạt động của một máy chủ.
`const os = require('os')`
http://nodejs.org/api/os.html

os.tmpdir(); // Returns the operating system's default directory for temp files.
os.endianness(); // Returns the endianness of the CPU. Possible values are "BE" or "LE".
os.hostname(); // Returns the hostname of the operating system.
os.type(); // Returns the operating system name.
os.platform(); // Returns the operating system platform.
os.arch(); // Returns the operating system CPU architecture.
os.release(); // Returns the operating system release.
os.uptime(); // Returns the system uptime in seconds.
os.loadavg(); // Returns an array containing the 1, 5, and 15 minute load averages.
os.totalmem(); // Returns the total amount of system memory in bytes.
os.freemem(); // Returns the amount of free system memory in bytes.
os.cpus(); // Returns an array of objects containing info about each CPU/core
os.networkInterfaces(); // Get a list of network interfaces.
os.EOL; // A constant defining the appropriate End-of-line marker for OS

## 33. Buffer
Buffer là một vùng dự trữ tạm thời chứa các dữ liệu đang được chuyển từ nơi này đến nơi khác.
Buffer có kích thước xác định và giới hạn.
Sử dụng Buffer khi muốn kiểm soát từng Byte dữ liệu truyền đến và đi.
http://nodejs.org/api/buffer.html

new Buffer(size);
new Buffer(array);
new Buffer(str, [encoding]);

// Returns true if the encoding is a valid encoding argument, or false otherwise.
Buffer.isEncoding(encoding);

Buffer.isBuffer(obj);
Buffer.concat(list, [totalLength]);
Buffer.byteLength(string, [encoding]);

// Writes string to the buffer at offset using the given encoding
buf.write(string, [offset], [length], [encoding]);

// Decodes and returns a string from buffer data encoded with encoding (defaults to 'utf8')
// beginning at start (defaults to 0) and ending at end (defaults to buffer.length).
buf.toString([encoding], [start], [end]);

// Returns a JSON-representation of the Buffer instance,
// which is identical to the output for JSON Arrays
buf.toJSON();

// Does copy between buffers. The source and target regions can be overlapped
buf.copy(targetBuffer, [targetStart], [sourceStart], [sourceEnd]);
buf.slice([start], [end]);
buf.fill(value, [offset], [end]);
buf[index];
buf.length;

buffer.INSPECT_MAX_BYTES;
called. This can be overridden by user modules.



# 34. Nodemon
Nodemon sẽ luôn theo dõi sự thay đổi của các files trong thư mục,
nếu có bất kì thay đổi nào trong file nó sẽ build lại ứng
dụng ==> rất thích hợp để chạy trên môi trường dev,
cần xem sự thay đổi ngay khi chỉnh sửa source code.

```bash
$ nodemon bin/www
```

# 35. Node PortFinder
Tìm port đang mở hoặc domain socket trên máy đang chạy.

```js
var portfinder = require('portfinder');
var port = 3000;
var portSpan = 999;
portfinder.getPort({
port: port, // minimum port number
stopPort: port + portSpan // maximum port number
}, function (err, openPort) {
if (err) throw err;
port = openPort;
});
```

# 36. Nodejs Cluster
Node.js chỉ chạy một process duy nhất.
Trên một machine có nhiều CPU thì mặc định NodeJS cũng chỉ chạy trên 1 CPU mà thôi.
Lãng phí mất các CPU kia, không sử dụng.
==>
Chúng ta sẽ tạo ở mỗi CPU, sẽ chạy một NodeJS process.
Thêm vào đó khi 1 process bị crash thì các process khác vẫn còn chạy,
nên app vẫn chạy được bình thường.

```js
var cluster = require('cluster');
var workers = process.env.WORKERS || require('os').cpus().length;

if (cluster.isMaster) {
console.log('Master cluster is running on %s with %s workers', process.pid, workers);
for (var i = 0; i < workers; ++i) {
var worker = cluster.fork().process;
console.log('worker %s on %s started', i+1, worker.pid);
}
cluster.on('exit', function(worker, code, signal) {
console.log('worker %s died. restarting...', worker.process.pid);
cluster.fork();
});
}

if (cluster.isWorker) {
// Server code
}
```

# 37. Logger - Morgan & Winston

-------------------- Morgan Module
Morgan - là 1 middleware logger for NodeJS

```js
var logger = require('morgan');
app.use(logger('dev'));
app.use(logger(':remote-addr :remote-user :datetime :req[header] :method
:url HTTP/:http-version :status :res[content-length] :res[header]
:response-time[digits] :referrer :user-agent', {
stream: accessLogStream
}));
```

-------------------- Winston Module
https://github.com/winstonjs/winston
Winston - cũng là một module logger phổ biến, hỗ trợ nhiều transports (Console, File..)

```js
var winston = require('winston');
var logger = winston.createLogger({
format: winston.format.combine(
winston.format.colorize({
all: true
}),
winston.format.printf(
data => `${data.level} : ${data.message}`
)
),
transports: [
new winston.transports.Console({
level: 'silly'
}),
new winston.transports.File({
level: 'silly',
filename: './log/ServerData.log'
})
]
});
```

## 38. Module lodash
https://lodash.com/docs/4.17.15#concat
Viết sẵn rất nhiều function xử lý mảng, chuỗi, các hàm tính toán, xử lý vòng lặp...

## 39. Module moment
Xử lý ngày tháng với momment.
npm install moment --save

https://momentjs.com/docs/
https://www.npmjs.com/package/moment
https://dzone.com/articles/using-momentjs-in-nodejs

## 40. crypto
https://nodejs.org/en/knowledge/cryptography/how-to-use-crypto-module/
Mã hóa password với crypto.

## 41. Joi
https://www.npmjs.com/package/joi
https://dev.to/itnext/joi-awesome-code-validation-for-node-js-and-express-35pk
Validation input params with Joi.

## 42. Module vhost
https://www.npmjs.com/package/vhost
Phân tách môi trường, hoặc chức năng dựa theo domain.

# 43. Rotating File Stream

To provide an automated rotation of Express/Connect logs
or anything else that writes to a log on a regular basis that needs to be rotated
based on date.

```js
var rfs = require('rotating-file-stream');
var accessLogStream = rfs('file.log', {
size: '10M', // rotate every 10 MegaBytes written
interval: '1d', // rotate daily
compress: 'gzip' // compress rotated files
path: 'log' // folder path for log files
});
```

# 44. MySQL Database Connectivity (with connection pool)

This is a node.js driver for mysql. Also implemented the connection pool,
it is a cache of database connections maintained
so that the connections can be reused when future requests to the database are required.
Connection pools are used to enhance the performance of executing commands on a database.

```js
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit : 50,
queueLimit: 100,
host : '127.0.0.1', // The hostname of the database you are connecting to.
port : 3306, // The port number to connect to. (Default: 3306)
user : 'arjun', // The MySQL user to authenticate as.
password : '', // The password of that MySQL user.
database : 'mysqldb', // Name of the database to use for this connection.
connectTimeout : 10000, // The milliseconds before a timeout occurs during the initial
waitForConnections: true, // Determines the pool's action when no connections
acquireTimeout: 10000, // The milliseconds before a timeout occurs during the connection
debug : false // Prints protocol details to stdout. (Default: false)
});
```

# 45. Server Status Monitor

Express Status Monitor is simple,
self-hosted module based on Socket.io and Chart.js to report realtime server metrics
for Express-based ode servers.

```js
app.use(require('express-status-monitor')({
title: 'Server Status', // title for status screen
path: '/status', // path for server status invokation
spans: [{
interval: 1, // every second
retention: 60 // keep 60 datapoints in memory
}],
chartVisibility: {
cpu: true, // enable CPU Usage
mem: true, // enable Memory Usage
load: true, // enable One Minute Load Avg
responseTime: true, // enable Response Time
rps: true, // enable Requests per Second
statusCodes: true // enable Status Codes
},
healthChecks: [{
protocol: 'http', // protocol
host: 'localhost' // server host name
path: '/users', // endpoint to check status
port: '3000' // server port
}] // health check will be considered successful if the endpoint returns a 200 status code
}));
```

## 46. mysql2
https://www.npmjs.com/package/mysql2
Module hỗ trợ viết mysql query thuần.

## 47. sequelize
https://www.npmjs.com/package/sequelize
https://sequelize.org/master/
Sequelize is a promise-based Node.js ORM tool for Postgres,
MySQL, MariaDB, SQLite and Microsoft SQL Server.
Module hỗ trợ tương tác với DB thông qua các đối tượng(Object)

## 48. body-parser
https://www.npmjs.com/package/body-parser
Node.js body parsing middleware.
Parse incoming request bodies in a middleware before your handlers,
available under the `req.body` property.

## 49. cors
https://www.npmjs.com/package/cors
Cấu hình chia sẻ tài nguyên đa nguồn gốc(Cross-Origin Resource Sharing)



NodeJS cơ bản



## Khái niệm Nodejs
Nodejs là một nền tảng (Platform) phát triển độc lập được xây dựng
ở trên Javascript Runtime của Chrome mà chúng ta có thể xây dựng được
các ứng dụng mạng một cách nhanh chóng và dễ dàng mở rộng.

Phần Core bên dưới của Nodejs được viết hầu hết bằng C++
nên cho tốc độ xử lý và hiệu năng khá cao.

Nodejs tạo ra được các ứng dụng có tốc độ xử lý nhanh, realtime thời gian thực.


## Những ứng dụng nên viết bằng Nodejs
1. Websocket server: Các máy chủ web socket như là Online Chat, Game Server…
2. Fast File Upload Client: là các chương trình upload file tốc độ cao.
3. Ad Server: Các máy chủ quảng cáo.
4. Cloud Services: Các dịch vụ đám mây.
5. RESTful API: đây là những ứng dụng mà được sử dụng cho các ứng dụng khác thông qua API.
6. Any Real-time Data Application:
bất kỳ một ứng dụng nào có yêu cầu về tốc độ thời gian thực.
Micro Services: Ý tưởng của micro services là chia nhỏ một ứng dụng lớn thành
các dịch vụ nhỏ và kết nối chúng lại với nhau. Nodejs có thể làm tốt điều này.


## Chú ý
1. Các ứng dụng Nodejs được viết bằng javascript,
ngôn ngữ này là một ngôn ngữ khá thông dụng.

2. Nodejs chạy đa nền tảng phía Server, sử dụng kiến trúc hướng sự kiện Event-driven,
cơ chế non-blocking I/O làm cho nó nhẹ và hiệu quả.

3. Có thể chạy ứng dụng Nodejs ở bất kỳ đâu trên máy Mac – Window – Linux,
hơn nữa cộng đồng Nodejs rất lớn và hoàn toàn miễn phí.

4. Các ứng dụng NodeJS đáp ứng tốt thời gian thực và chạy đa nền tảng, đa thiết bị.

5. Xử lý đơn luồng (single thread)

## Cài đặt
https://nodejs.org/en/download/

## Sử dụng cơ bản
Tạo mới file `package.json`: `npm init`
Install thư viện http: `npm i http`

Tạo mới file index.js:
<!-->
// Import thư viện HTTP (HTTP Module)
var http = require("http");

// Khởi tạo 1 máy chủ HTTP với port 8888
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World!");
response.end();
}).listen(8888);
<-->

==>
chạy command: `node index.js` để tạo mới 1 máy chủ HTTP
và sau đó vào 1 browser bất kì mở http://localhost:8888/ để xem kết quả.

- Tạo máy chủ HTTP lắng nghe ở cổng 8888, tuy nhiên không thực thi gì:
<!-->
var http = require("http");
var server = http.createServer();
server.listen(8888);
<-->


## sử dụng hàm
function say(word) {
console.log(word);
}

function execute(someFunction, value) {
// đưa biến value vào function `someFunction` để xử lý
someFunction(value);
}

execute(say, "Hello");

- Anonymous function
function execute(someFunction, value) {
someFunction(value);
}

execute(function(word){ console.log(word) }, "Hello");


## Cơ chế xử lý request
var result = database.query("SELECT * FROM hugetable");
console.log("Hello World");

Giả sử thao tác đến database diễn ra rất chậm, có rất nhiều bản ghi thoả mãn yêu cầu,
thời gian thực thi có thể mất đến vài giây.

Trong mô hình thực thi của PHP thì đó không phải là vấn đề đáng quan tâm:
`máy chủ web PHP khởi tạo một process riêng cho mỗi request nó nhận được`.
Nếu một trong những request này chậm hơn bình thường,
nó chỉ có thể ảnh hưởng đến thời gian tải trang của người tạo ra request đó,
chứ không gây ảnh hưởng đến những người dùng khác.

Mô hình thực hiện của Node.js không giống như vậy - nó chỉ dùng duy nhất một process.
Nếu có truy vấn tới database nào đó tốn nhiều thời gian, nó sẽ làm chậm toàn bộ process
- mọi thứ sẽ bị dừng lại cho đến khi truy vấn kia kết thúc.

Để tránh tình trạng này xảy ra,
JavaScript và Node.js đưa ra khái niệm "dựa theo sự kiện" (event-driven),
gọi ngược không đồng bộ (asynchronous callback),
bằng cách sử dụng một "vòng lặp sự kiện" (event loop).

- Cải tiến với asynchronous library
// truy vấn tới database một cách không đồng bộ
database.query("SELECT * FROM hugetable", function(rows) {
var result = rows;
});
console.log("Hello World");

Thay vì phải chờ xử lý gọi DB như trước, với cải tiến sử dụng bất đồng bộ này,
Node JS gửi truy vấn đến DB và ghi nhận lại là đang chờ xử lý sau đó sẽ xử lý tiếp cái khác.
Đến một thời điểm nào đó trong tương lai - khi truy vấn kết thúc, kết quả được trả về
- nó sẽ phải thực hiện những gì được viết trong hàm vô danh.

Ở phần code trên. Dòng chữ "Hello World" được in ra ngay lập tức trên console.
Sau đó bắt đầu một vòng lặp vô tận, và cứ thế chờ đợi,
không xử lý bất kỳ gì khác cho đến khi có một sự kiện nào đó đánh thức nó,
ví dụ như truy vấn tới database đã có dữ liệu trả về.

Mô hình thực thi không đồng bộ, đơn luồng,
và dựa trên sự kiện này không phải thứ gì đó hoàn hảo tuyệt đối.
Nó chỉ là một trong nhiều mô hình đang tồn tại, nó cũng có những nhược điểm,
một trong số đó chính là: nó chỉ có thể chạy trên một nhân của CPU mà thôi.

var http = require("http");

// Khi một request đến server. hàm onRequest sẽ được gọi
function onRequest(request, response) {
console.log("Request received.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}

http.createServer(onRequest).listen(8888);

console.log("Server has started.");

==>
Chạy `node server.js` sẽ thấy ở màn hình console in ra `Server has started.`
Và mỗi một request đến server, màn hình console sẽ in ra `Request received.`


## Xử lý đơn luồng (single thread)
Máy ảo và OS sẽ chạy I/O song song và khi trở lại Javascript code,
phần Javascript code sẽ chỉ chạy đơn luồng.
Nói cách khác, tất cả mọi thứ chạy song song, ngoại trừ Javascript code,
Nếu tất cả những gì ta làm là asynchronous I/O.

// call asynchronous to get data in DB
db.findOne('SELECT ... LIMIT 1', function(err, result) {
if (err) return console.error(err)
console.log(result)
})
console.log('Running query')
setTimeout(function() {
console.log('Hey there')
}, 1000)

Có thể lệnh query đến database sẽ tốn hơn một phút nhưng dòng chữ "Running query"
sẽ xuất hiện ngay sau khi tạo lệnh query.
Và ta sẽ thấy dòng chữ "Hey there" sau một giây sau khi tạo lệnh query dù query
có đang chạy hay không.
Nodejs app chỉ gọi function mà không block việc thực thi của các phần code khác.
Nó sẽ được thông báo thông qua function callback khi lệnh query chạy xong
và ta sẽ thu được kết quả.


## các tác vụ chiếm dụng CPU
db.findAll('SELECT ...', function(err, results) {
if (err) return console.error(err)
// Heavy computation and many results
for (const encrypted of results) {
const plainText = decrypt(encrypted)
console.log(plainText)
}
})

Trong trường hợp này, chúng ta có quá nhiều kết quả và cần phải tính toán phức tạp,
nặng nề trên các kết quả đó.
Điều này có thể mất vài giây, và trong thời gian này việc thực thi
các phần Javascript khác sẽ bị queue,
điều đó có nghĩa ta sẽ block tất cả các user trong thời gian này
nếu ta đang chạy một server trên cùng một app.

==>
- Cách 1: Sử dụng setImmediate(callback) để đưa function xử lý vào lại hàng đợi

function processChunk() {
if (arr.length === 0) {
// code that runs after the whole array is executed
}
else {
console.log('processing chunk');
// pick 10 items and remove them from the array
const subarr = arr.splice(0, 10)
for (const item of subarr) {
// do heavy stuff for each item on the array
doHeavyStuff(item)
}

// Put the function back in the queue
setImmediate(processChunk)
}
}

processChunk()

Bây giờ ta sẽ chỉ xử lý mỗi lần 10 item và gọi setImmediate(callback)
vì vậy nếu có việc gì khác mà chương trình cần phải làm,
nó sẽ được thực hiện chen giữa các khối 10 item.

- Cách 2: trigger một node cron jobs


## Tạo một custom module
Biến một đoạn code thành một module có nghĩa là chúng ta phải trích xuất (`export`)
một phần chức năng mà chúng ta muốn
(từ một file nào đó, hay cả file) để đưa vào module kia.

- Tạo module server
var http = require("http");

function start() {
function onRequest(request, response) {
console.log("Request received.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}

http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}

exports.start = start;

- Sử dụng module
Tạo mới file index.js với nội dung sau:
var server = require("./server");
server.start();

- Ta có thể export ra một const, functions hay class
module.exports = {
groupCloudFunctions: {
mobile: buyerGroupCloudFunction,
web: operatorGroupCloudFunction,
},
allCloudFunctionNames,
hasCloudFunction: (fnName) => allCloudFunctionNames.includes(fnName),
}

- Export một object
const InitData = require("./initData")
const UpdateOrderAmountShopAndItem = require("./updateOrderAmountShopAndItem")
...
module.exports = Object.assign({
// createDefaultCategories: createCategories,
InitData,
UpdateOrderAmountShopAndItem,
UpdateItemsStatus,
AddIndexSchema,
DeleteImage,
})


## Các thành phần của Node JS

- Modules, Error Handling
- Debugger, Streaming, DNS, Domain, Global, Net
- Console, Cluster, Add-ons, Buffer, Callbacks, Crypto


## If else
if (time < 10) {
greeting = "Good morning";
} else if (time < 20) {
greeting = "Good day";
} else {
greeting = "Good evening";
}


## switch case
switch(expression) {
case x:
// code block
break;
case y:
// code block
break;
default:
// code block
}


## for
var array = ['C++', 'Java', 'JavaScript', 'NodeJS'];
for(var i = 0; i < array.length; i++){
console.log(array[i]);
}

- For .. of:
var results = [1,2];
for (let item of results) {
console.log(item);
}

- for .. of with key and value:
const object1 = {a: 'somestring', b: 42};
for (const [key, value] of Object.entries(object1)) {
console.log(`${key}: ${value}`);
}

- for .. in:
const object2 = { a: 1, b: 2, c: 3 };
for (const property in object) {
console.log(`${property}: ${object[property]}`);
}


## While
while (condition) {
// execute code as long as condition is true
}


## do .. while
do {
do_work();
} while (condition);


## For each
- for each a list string
const arr = ['cat', 'dog', 'fish'];
arr.forEach(element => {
console.log(element);
});

- for each a list number
const arr = [1, 2, 3, 8, 7];
arr.forEach(element => {
console.log(element);
});

- for each with key and value
var reversed = fields.slice().reverse()
reversed.forEach(function (item, index) {
// ...
});

- For each with `lodash`/forEach Module
const _ = require('lodash')
// OR const _forEach = require("lodash/forEach")

const processItems = async (orderItems, isOperator = false) => {
let itemIds = Helper.extractToArray(orderItems, 'id')
let items = await ItemModel.getItemListByItemIds(itemIds, undefined, true, isOperator)
_.forEach(items, (item, index) => {
orderItems[index].images = item.images
orderItems[index].slug = item.slug || ""
orderItems[index].shopSlug = item.shop.slug || ""
delete orderItems[index].image
})
return orderItems
}


## 2. For - array with object element
var arrayB = [1,2,3,{"fruit":"orange", "drink":"beer"}];
document.write("2. Array: " + arrayB.join());

for (var j=0; j < arrayB.length; j++) {
if (typeof arrayB[j] == "object") {
var obj = arrayB[j];
for (var prop in obj) {
// skip loop if the property is from prototype
if(!obj.hasOwnProperty(prop)) continue;
// output key and object value
document.write(prop + " = " + obj[prop]);
}
}
else {
document.write(j.toString() + ":" + arrayB[j]);
}
}


## 3. multi-dimensional arrays
var arr = [['a', 'b'], ['c','d']];

for (var arrayIndex in arr) {
if (Array.isArray(arr[arrayIndex])) {
var arrTmp = arr[arrayIndex];
for (var z=0; z<arrTmp.length; z++) {
document.write(z.toString() + ":" + arrTmp[z]);
}
}
// document.write(arr[arrayIndex][0] + ' ' + arr[arrayIndex][1]);
}


## 4. Normal Object
var validation_messages = {
"key_1": {"your_name": "jimmy", "your_msg": "hello world"},
"key_2": {"your_name": "billy", "your_msg": "foo equals bar"}
}

for (var index in validation_messages) {
for (const [key, value] of Object.entries(validation_messages[index])) {
console.log("key: "+key+". value:"+value);
}
}


## 5. Process JSON Data
var objJSON = JSON.parse('{ "name":"Krunal", "age":25, "city":"Rajkot", "degree": "BE"}');

for (var prop in objJSON) {
console.log(prop + " = " + objJSON[prop]);
}

for (const [key, value] of Object.entries(objJSON)) {
console.log(key + " = " + value);
}





Tự học NodeJS

1. NodeJS cơ bản

2. Node module phổ biến

3. Xử lý đa luồng

4. Cấu hình Nodemon

5. Xóa đi tất cả các node process

MongoDB Cheat Sheet




## Show All Databases
show dbs

## Show Current Database
db

## Create Or Switch Database
use acme

## Drop
db.dropDatabase()

## Create Collection
db.createCollection('posts')

## Show Collections
show collections

## Insert Row
db.posts.insert({
title: 'Post One',
body: 'Body of post one',
category: 'News',
tags: ['news', 'events'],
user: {
name: 'John Doe',
status: 'author'
},
date: Date()
})

## Insert Multiple Rows
db.posts.insertMany([
{
title: 'Post Two',
body: 'Body of post two',
category: 'Technology',
date: Date()
},
{
title: 'Post Three',
body: 'Body of post three',
category: 'News',
date: Date()
},
{
title: 'Post Four',
body: 'Body of post three',
category: 'Entertainment',
date: Date()
}
])

## Update Row
db.posts.update({ title: 'Post Two' },
{
title: 'Post Two',
body: 'New body for post 2',
date: Date()
},
{
upsert: true
})

## Update Specific Field
db.posts.update({ title: 'Post Two' },
{
$set: {
body: 'Body for post 2',
category: 'Technology'
}
})

## Increment Field (\$inc)
db.posts.update({ title: 'Post Two' },
{
$inc: {
likes: 5
}
})

## Rename Field
db.posts.update({ title: 'Post Two' },
{
$rename: {
likes: 'views'
}
})

## Delete Row
db.posts.remove({ title: 'Post Four' })

## Sub-Documents
db.posts.update({ title: 'Post One' },
{
$set: {
comments: [
{
body: 'Comment One',
user: 'Mary Williams',
date: Date()
},
{
body: 'Comment Two',
user: 'Harry White',
date: Date()
}
]
}
})

## Add Index
db.posts.createIndex({ title: 'text' })

## Get All Rows
db.posts.find()

## Get All Rows Formatted
db.posts.find().pretty()

## Find Rows
db.posts.find({ category: 'News' })

## Sort Rows
- asc
db.posts.find().sort({ title: 1 }).pretty()
- desc
db.posts.find().sort({ title: -1 }).pretty()

## Count Rows
db.posts.find().count()
db.posts.find({ category: 'news' }).count()

## Limit Rows
db.posts.find().limit(2).pretty()

## Chaining
db.posts.find().limit(2).sort({ title: 1 }).pretty()

## Foreach
db.posts.find().forEach(function(doc) {
print("Blog Post: " + doc.title)
})

## Find One Row
db.posts.findOne({ category: 'News' })

## Find Specific Fields
db.posts.find({ title: 'Post One' }, {
title: 1,
author: 1
})

## Find By Element in Array (\$elemMatch)
db.posts.find({
comments: {
$elemMatch: {
user: 'Mary Williams'
}
}
}
)

## Text Search
db.posts.find({
$text: {
$search: "\"Post O\""
}
})

## Greater & Less Than
db.posts.find({ views: { $gt: 2 } })
db.posts.find({ views: { $gte: 7 } })
db.posts.find({ views: { $lt: 7 } })
db.posts.find({ views: { $lte: 7 } })



Học lập trình web căn bản với PHP

Bài 1: Các kiến thức căn bản Part 1:  https://jimmyvan88.blogspot.com/2012/05/can-ban-lap-trinh-web-voi-php-bai-1-cac.html Part 2:  https://...