Monday, October 7, 2013

NodeJS part I: Asynchronous I/O dan Event-driven


Pada artikel terdahulu di Bisakomputer.com, saya pernah menulis tutorial artikel tentang pembuatan web dengan platform nodejs. Pada bahasan NodeJS  ini saya akan coba menulis ke dalam tiga bagian artikel, dan pada artikel pertama ini, saya akan memberikan contoh pemrograman NodeJS dengan beberapa operasi synchronous dan operasi asynchronous I/O event-driven yang juga dimiliki oleh NodeJS. Disini saya ingin menunjukkan kekuatan yang dimiliki NodeJS untuk membangun aplikasi server dan real-time website.

Definisi synchronous dan asynchronous I/O event-driven

Asynchronous disini berarti non-blocking I/O. Ini berarti setiap operasi asynchronous harus segera mungkin mengembalikan nilai agar program tidak perlu menunggu proses baca tulis ke I/O. I/O sendiri adalah komponen sebuah mesin atau komputer untuk urusan input dan output data. Komponen I/O memiliki kecepatan baca tulis jauh lebih kecil dari kecepatan prosesor dalam memproses data. Kebalikan dari asynchronous, sebuah program yang menjalankan operasi synchronous akan menunggu operasi itu selesai baru kemudian program dapat melanjutkan operasi lainnya.
Sedangkan istilah event-driven disini sama dengan event-based programming yaitu urutan atau flow program ditentukan oleh sebuah events. Jika diartikan secara bahasa event itu sama dengan kejadian, sedangkan Wiki mendefinisikan events ini dengan perubahan pada sebuah kondisi objek. Perpindahan mouse dari window satu ke window lain, penekanan tut-tut keyboard, sampai pada request halaman website. Paling dasar sekaligus terpenting dari event-driven ini adalah event-handler atau callbackCallback ini sebuah fungsi atau subroutine yang bisa sebagai argument pada operasi-operasi asynchronous. Dia akan dipanggil sekali setelah operasi selesai dilakukan.
Di dalam NodeJS terdapat operasi-operasi yang sifatnya synchronous dan asynchronous, tapi keunggulan NodeJS ini ada pada non-blocking I/O alias asynchronous nya.
Asynchronous dan event-driven yang ada pada NodeJS ini disebut-sebut sebagai bentuk pemrograman baru dari pendahulunya, multi-threaded. Berikut adalah dua program yang mengerjakan operasi yang sama tapi berbeda, satu menggunakan synchronous dan yang satunya lagi menggunakan asynchronous
var fs = require('fs');
try {
 var data = fs.readFileSync('README.md', 'ascii');
 console.log(data);
}catch (err) {
 console.error("There was an error opening the file:");
 console.log(err);
}
Operasi membaca atau memperoleh data file yang dilakukan program diatas, menggunakan operasi synchronous readFileSync(). Program tidak akan melanjutkan operasi lain sebelum readFileSync() selesai dieksekusi dan mengembalikan teks file README.md. Ketika menggunakan operasi synchronous terkadang juga mengembalikan exception atau kesalahan, sehingga penggunaan try/catch harus dilakukan untuk kestabilan dan debugging program. Pemrograman seperti diatas tentu tidak asing lagi bagi Anda, karena hampir semua pemrograman yang Anda lakukan memiliki operasi synchronous seperti diatas.
var fs = require('fs');
fs.readFile('README.md', 'ascii', function(err,data){
 if(err) {
 console.error("Could not open file: %s", err);
 process.exit(1);
 }
console.log(data.toString('ascii'));
});
Program ini sama dengan program yang pertama, yaitu mendapatkan isi dari sebuah file README tapi bedanya pada penggunaan fungsi operasi asynchronous. Pada program yang kedua ini menggunakan fungsi asynchronous readFile(). Semua fungsi asynchronous nodejs memiliki argument callback yang biasanya harus dimasukkan pada akhir parameter. Fungsi readFile() diatas memiliki callback yang akan beroperasi untuk display isi file ke console. Ini dilakukan jika operasi readFile() selesai dilakukan.

Kemudahan Asynchronous I/O dan Event-driven NodeJS

1. Independent Code
Prinsipnya semua operasi yang dependent terhadap operasi asynchronous dapat diletakkan pada callback operasi asynchronous tersebut. Hal ini tentunya dapat menciptakan blok-blok operasi yang independent terhadap yang lain.
2. Nested Callbacks
Pada pemrograman synchronous, fungsi operasi tergantung pada operasi lain yang berada pada baris atasnya, ini yang dinamakan dengan linier sequence. Tetapi pada nodejs dengan dukungan asynchronous dan event-driven nya, urutan eksekusi operasi dapat dilakukan dengan nested callbacks. Ini bukan dari atas ke bawah seperti pada linier sequence, tapi secara prinsip fungsi callback dieksekusi setelah fungsi asynchronous selesai dilakukan.
var fs = require('fs');
var Filename='README.md';
fs.chmod(Filename, 777, function (err) { 
 fs.rename(Filename, "READ.md", function (err) {
 fs.stat("READ.md", function (err, stats) {
 var isFile = stats.isFile();
  });
 });
});
Pada contoh program diatas, terdapat tiga operasi yang dilakukan. Mengubah permission file README.md, mengubah nama file README.md dan terakhir mendapatkan informasi seputar file READ.md. Callback fungsi chmod() merupakan fungsi rename(), sedangkan callback rename() adalah stat(). Dengan cara nested callbacks seperti inilah urutan eksekusi program dilakukan.
3. Parallelisation
non-blocking I/O pada NodeJS memungkinkan untuk menjalankan operasi-operasi secara pararel. Kode program berikut adalah contoh parallelisation operasi fungsi stat(). Tujuan dari program ini adalah menghitung total size file pada sebuah direktori.
var fs = require('fs');
var count = 0,
 totalBytes = 0;
fs.readdir(".", function (err, filenames) {
 var i;
 count = filenames.length;
 for (i = 0; i < filenames.length; i++) {
 fs.stat("./" + filenames[i], function (err, stats) {
 totalBytes += stats.size;
 count--;
 if (count === 0) {
 console.log(totalBytes);
 }
 });
 }
 });
Fungsi stat() akan dilakukan pada masing-masing file. Tiap fungsi stat() akan dijalankan secara pararel satu dengan lainnya.
4. Code Reuse
Dalam pemrograman NodeJS, Anda dapat me-wrapper kode yang Anda buat kedalam sebuah fungsi. Semua bahasa pemrograman apapun tentunya dapat melakukannya, tapi kemudahaannya disini adalah kode yang di-wrapper dapat dimasukkan sebagai argument pada fungsi lain.
var fs = require('fs');
var path1 = "./",
 path2 = ".././",
 logCount;
function countFiles(path, callback) {
 fs.readdir(path, function (err, filenames) {
 callback(err, path, filenames.length);
 });
}
logCount = function (err, path, count) {
 console.log(count + " files in " + path);
};
countFiles(path1, logCount); 
countFiles(path2, logCount);
Pada contoh, kita me-wrapper kode untuk display teks ke console dengan nama logCount. Sehingga kita dapat memakai ulang wrapper logCount pada operasi menghitung jumlah file pada path1 dan juga operasi pada path2.

Penutup

Pada artikel pertama ini merupakan dasar pemrograman yang ada pada NodeJS. Kekuatan NodeJS itu terletak pada asynchronous I/O dan event-driven nya, sehingga untuk membangun aplikasi server atau website yang berjalan diatasnya, kita harus memahami dulu kedua istilah ini dan bagaimana penerapannya pada NodeJS.
Beberapa aplikasi keren sudah banyak yang dibuat diatas platform ini, diantaranya yang saya ketahui adalah Blaast Backend (http://blaast.com/) yang dibangun diatas NodeJS, sebuah tool kolaborasi projek yaitu trello (https://trello.com/), dan lagi sebuah IDE online development yaitu Cloud9 IDE (https://c9.io/).

*Artikel ini pernah publis di bisakomputer.com tertanggal 17 Juli 2012

No comments:

Post a Comment