Advertisement
  1. Code
  2. JavaScript

Aplikasi Satu-Halaman Yang Lebih Responsif Dengan AngularJS & Socket.IO: Membuat Perpustakaan

Scroll to top
Read Time: 11 min

Indonesian (Bahasa Indonesia) translation by Sayektisri1967 (you can also view the original English article)

Baik HTML maupun HTTP tidak dibuat untuk aplikasi web dinamis. Kami pada dasarnya bergantung pada peretasan, di luar peretasan untuk memberi aplikasi kami antarmuka pengguna yang responsif. AngularJS menghapus beberapa batasan dari HTML, memungkinkan kita untuk membuat dan mengelola kode antarmuka pengguna lebih mudah. Socket.IO, di sisi lain membantu kami mengirim data dari server tidak hanya ketika permintaan klien, tetapi juga ketika server perlu. Dalam artikel ini saya akan menunjukkan kepada Anda bagaimana menggabungkan keduanya, untuk meningkatkan respon dari aplikasi satu halaman Anda.


Pengenalan

Pada bagian pertama dari tutorial ini kita akan membuat layanan AngularJS yang dapat digunakan kembali untuk Socket.IO. Karena itu bagian yang dapat digunakan kembali, ini akan menjadi sedikit lebih rumit daripada hanya menggunakan module.service () atau module.factory (). Kedua fungsi ini hanyalah gula sintaksis di atas metode level.provider () yang lebih rendah, yang akan kita gunakan untuk menyediakan beberapa opsi konfigurasi. Jika Anda belum pernah menggunakan AngularJS sebelumnya, saya sangat menyarankan Anda untuk setidaknya mengikuti tutorial resmi dan beberapa tutorial di sini di Tuts +.


Persiapan: The Back-End

Sebelum kami mulai menulis modul AngularJS kami, kami memerlukan back-end sederhana untuk pengujian. Jika Anda sudah akrab dengan Socket.IO, Anda cukup menggulir ke bagian akhir bagian ini, salin sumber back-end dan lanjutkan ke yang berikutnya, jika tidak - baca terus.

Modul yang Diperlukan

Kami hanya perlu socket.io. Anda dapat menginstalnya langsung menggunakan perintah npm seperti ini:

1
npm install socket.io
2
 

Atau buat file package.json, masukkan baris ini di bagian dependencies

1
"socket.io": "0.9.x"
2
 

Dan jalankan perintah npm install

Membuat Server Socket.IO

Karena kita tidak memerlukan kerangka web rumit seperti Express, kita dapat membuat server menggunakan Socket.IO:

1
var io = require('socket.io')(8080);
2
 

Itu saja yang Anda butuhkan untuk mengatur server Socket.IO. Jika Anda memulai aplikasi, Anda akan melihat keluaran serupa di konsol:

Dan Anda harus dapat mengakses file socket.io.js di browser Anda di http://localhost:8080/socket.io/socket.io.js:

Menangani Koneksi

Kami akan menangani semua koneksi masuk dalam connectionpendengar acara  dari objek io.sockets:

1
io.sockets.on('connection', function (socket) {
2
 
3
 });
4
 

Atribut socket yang dilewatkan ke callback adalah klien yang terhubung dan kita dapat mendengarkan kejadian di dalamnya.

Pendengar Dasar

Sekarang kita akan menambahkan listener kejadian dasar dalam callback di atas. Ini akan mengirim data yang diterima, kembali ke klien menggunakan metode socket.emit ():

1
  socket.on('echo', function (data) {
2
 		socket.emit('echo', data);
3
 	});
4
 

echo adalah nama acara khusus yang akan kita gunakan nanti.

Pendengar dengan pengakuan

Kami juga akan menggunakan ucapan terima kasih di perpustakaan kami. Fitur ini memungkinkan Anda untuk melewatkan fungsi sebagai parameter ketiga dari metode socket.emit (). Fungsi ini dapat dipanggil di server untuk mengirim beberapa data kembali ke klien:

1
	socket.on('echo-ack', function (data, callback) {
2
 		callback(data);
3
 	});
4
 

Ini memungkinkan Anda untuk menanggapi klien tanpa mengharuskannya untuk mendengarkan acara apa pun (yang berguna jika Anda hanya ingin meminta beberapa data dari server).

Sekarang uji coba kami selesai. Kode akan terlihat seperti ini (ini adalah kode yang harus Anda salin jika Anda menghilangkan bagian ini):

1
var io = require('socket.io')(8080);
2
 
3
 io.sockets.on('connection', function (socket) {
4
 	socket.on('echo', function (data) {
5
 		socket.emit('echo', data);
6
 	});
7
 
8
 	socket.on('echo-ack', function (data, callback) {
9
 		callback(data);
10
 	});
11
 });
12
 

Anda sekarang harus menjalankan aplikasi dan membiarkannya berjalan sebelum melanjutkan dengan sisa tutorial.


Persiapan: Front-End

Kami tentu saja membutuhkan beberapa HTML untuk menguji pustaka kami. Kita harus memasukkan AngularJS, socket.io.js dari back-end, library angular-socket.js dan controller dasar AngularJS untuk menjalankan beberapa tes. Kontroler akan digarisbawahi di <head> dokumen untuk menyderhanakan alur kerja

1
<!DOCTYPE html>
2
 <html>
3
 <head>
4
 	<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
5
 	<script src="http://localhost:8080/socket.io/socket.io.js"></script>
6
 	<script src="angular-socket.js"></script>
7
 
8
 	<script type="application/javascript">
9
 		
10
 	</script>
11
 </head>
12
 <body>
13
 
14
 </body>
15
 </html>
16
 

Ini yang kami butuhkan untuk saat ini, kami akan kembali ke tag skrip kosong nanti karena kami belum memiliki perpustakaan.


Membuat Perpustakaan Socket.IO AngularJS

Di bagian ini kita akan membuat perpustakaan angular-socket.js. Semua kode harus dimasukkan ke dalam file ini.

Modul

Mari kita mulai dengan membuat modul untuk lib kita:

1
var module = angular.module('socket.io', []);
2
 

Kami tidak memiliki dependensi, sehingga array dalam argumen kedua dari angular.module () kosong, tetapi tidak menghapus sepenuhnya atau Anda akan mendapatkan $ injektor: nomod. Ini terjadi karena bentuk satu argumen dari angular.module () mengambil referensi ke modul yang sudah ada, daripada membuat yang baru.

Penyedia

Penyedia adalah salah satu cara untuk membuat layanan AngularJS. Sintaksnya sederhana: argumen pertama adalah nama layanan (bukan nama penyedia!) Dan yang kedua adalah fungsi konstruktor untuk penyedia:

1
module.provider('$socket', $socketProvider() {
2
 
3
 });
4
 

Pilihan konfigurasi

Untuk membuat perpustakaan dapat digunakan kembali, kita perlu memperbolehkan perubahan konfigurasi Socket.IO. Pertama mari kita mendefinisikan dua variabel yang akan memegang URL untuk koneksi dan objek konfigurasi (kode dalam langkah ini pergi ke fungsi $socketProvider()):

1
	var ioUrl = '';
2
 	var ioConfig = {};
3
 

Sekarang karena variabel-variabel ini tidak tersedia di luar fungsi $socketProvider() (mereka bersifat pribadi), kita harus membuat metode (setter) untuk mengubahnya. Kami tentu saja bisa membuat mereka menjadi publik seperti ini:

1
	this.ioUrl = '';
2
 	this.ioConfig = {};
3
 

Tapi:

  1. Kami harus menggunakan Function.bind () nanti untuk mengakses konteks yang sesuai untuk this
  2. Jika kita menggunakan setter, kita dapat memvalidasi untuk memastikan nilai yang tepat ditetapkan - kita tidak ingin menempatkan false sebagai opsi 'timeout'

Daftar lengkap opsi untuk Klien Socket.IO dapat dilihat di wiki GitHub mereka. Kami akan membuat setter untuk masing-masing ditambah satu untuk URL. Semua metode terlihat serupa, jadi saya akan menjelaskan kode untuk salah satu dari mereka dan meletakkan sisanya di bawah ini.

Mari kita menetapkan metode pertama:

1
	this.setConnectionUrl = function setConnectionUrl(url) {
2
 

Itu harus memeriksa jenis parameter berlalu dalam:

1
		if (typeof url == 'string') {
2
 

Jika itu yang kami harapkan, mengatur opsi:

1
			ioUrl = url;
2
 

Jika tidak, harus membuang TypeError:

1
		} else {
2
 			throw new TypeError('url must be of type string');
3
 		}
4
 	};
5
 

Untuk yang lainnya, kita dapat membuat fungsi pembantu agar tetap DRY:

1
	function setOption(name, value, type) {
2
 		if (typeof value != type) {
3
 			throw new TypeError("'"+ name +"' must be of type '"+ type + "'");
4
 		}
5
 
6
 		ioConfig[name] = value;
7
 	}
8
 

Itu hanya melempar TypeError jika jenisnya salah, jika tidak set nilai. Berikut adalah kode untuk sisa opsi:

1
	this.setResource = function setResource(value) {
2
 		setOption('resource', value, 'string');
3
 	};
4
 	this.setConnectTimeout = function setConnectTimeout(value) {
5
 		setOption('connect timeout', value, 'number');
6
 	};
7
 	this.setTryMultipleTransports = function setTryMultipleTransports(value) {
8
 		setOption('try multiple transports', value, 'boolean');
9
 	};
10
 	this.setReconnect = function setReconnect(value) {
11
 		setOption('reconnect', value, 'boolean');
12
 	};
13
 	this.setReconnectionDelay = function setReconnectionDelay(value) {
14
 		setOption('reconnection delay', value, 'number');
15
 	};
16
 	this.setReconnectionLimit = function setReconnectionLimit(value) {
17
 		setOption('reconnection limit', value, 'number');
18
 	};
19
 	this.setMaxReconnectionAttempts = function setMaxReconnectionAttempts(value) {
20
 		setOption('max reconnection attempts', value, 'number');
21
 	};
22
 	this.setSyncDisconnectOnUnload = function setSyncDisconnectOnUnload(value) {
23
 		setOption('sync disconnect on unload', value, 'boolean');
24
 	};
25
 	this.setAutoConnect = function setAutoConnect(value) {
26
 		setOption('auto connect', value, 'boolean');
27
 	};
28
 	this.setFlashPolicyPort = function setFlashPolicyPort(value) {
29
 		setOption('flash policy port', value, 'number')
30
 	};
31
 	this.setForceNewConnection = function setForceNewConnection(value) {
32
 		setOption('force new connection', value, 'boolean');
33
 	};
34
 

Anda bisa menggantinya dengan metode setOption()tunggal, tetapi tampaknya lebih mudah untuk mengetikkan nama opsi dalam kasus unta, daripada melewatkannya sebagai string dengan spasi.

Fungsi pabrik

Fungsi ini akan membuat objek layanan yang dapat kita gunakan nanti (misalnya di pengontrol). Pertama, mari kita panggil fungsi io () untuk terhubung ke server Socket.IO:

1
	this.$get = function $socketFactory($rootScope) {
2
 		var socket = io(ioUrl, ioConfig);
3
 

Perhatikan bahwa kita menetapkan fungsi ke properti $get dari objek yang dibuat oleh penyedia - ini penting karena AngularJS menggunakan properti itu untuk memanggilnya. Kami juga menempatkan $rootScope sebagai parameternya. Pada titik ini, kita dapat menggunakan injeksi ketergantungan AngularJS untuk mengakses layanan lain. Kami akan menggunakannya untuk menyebarkan perubahan pada model apa pun dalam callback Socket.IO.

Sekarang fungsi perlu kembali sebuah objek:

1
		return {
2
 
3
 		};
4
 	};
5
 

Kami akan menempatkan semua metode untuk layanan di dalamnya.

Metode on()

Metode ini akan melampirkan pendengar acara ke objek soket, sehingga kami dapat memanfaatkan data yang dikirim dari server:

1
			on: function on(event, callback) {
2
 

Kami akan menggunakan Socket.IO's socket.on() untuk melampirkan callback kami dan memanggilnya dalam lingkup AngularJS$scope.$aply () method. Ini sangat penting, karena model hanya dapat dimodifikasi di dalamnya:

1
				socket.on(event, function () {
2
 

Pertama, kita harus menyalin argumen ke variabel sementara sehingga kita bisa menggunakannya nanti. Argumen tentu saja segala sesuatu yang dikirim oleh server kepada kami:

1
					var args = arguments;
2
 

Selanjutnya, kita dapat memanggil callback kita menggunakan Function.apply () untuk meneruskan argumen ke sana:

1
					$rootScope.$apply(function () {
2
 						callback.apply(socket, args);
3
 					});
4
 				});
5
 			},
6
 

Ketika pemancar acara socket memanggil fungsi pendengar, ia menggunakan $ rootScope. $ Apply () untuk memanggil callback yang disediakan sebagai argumen kedua ke metode .on (). Dengan cara ini Anda dapat menulis pendengar acara seperti yang Anda lakukan untuk aplikasi lain menggunakan Socket.IO, tetapi Anda dapat memodifikasi model AngularJS di dalamnya.

Metode off ()

Metode ini akan menghapus satu atau semua pendengar acara untuk acara tertentu. Ini membantu Anda untuk menghindari kebocoran memori dan perilaku tak terduga. Bayangkan Anda menggunakan ngRoute dan Anda memasang beberapa pendengar di setiap pengontrol. Jika pengguna menavigasi ke tampilan lain, pengontrol Anda dihancurkan, tetapi pendengar acara tetap dilampirkan. Setelah beberapa navigasi dan kami akan memiliki kebocoran memori.

1
			off: function off(event, callback) {
2
 

Kami hanya perlu memeriksa apakah callback disediakan dan memanggil socket.removeListener () atau socket.removeAllListeners ():

1
				if (typeof callback == 'function') {
2
 					socket.removeListener(event, callback);
3
 				} else {
4
 					socket.removeAllListeners(event);
5
 				}
6
 			},
7
 

Metode emit ()

Ini adalah metode terakhir yang kita butuhkan. Seperti namanya, metode ini akan mengirim data ke server:

1
			emit: function emit(event, data, callback) {
2
 

Karena Socket.IO mendukung ucapan terima kasih, kami akan memeriksa apakah callback telah disediakan. Jika ya, kita akan menggunakan pola yang sama seperti pada metode on () untuk memanggil callback dalam lingkup $. $ Apply ():

1
				if (typeof callback == 'function') {
2
 					socket.emit(event, data, function () {
3
 						var args = arguments;
4
 
5
 						$rootScope.$apply(function () {
6
 							callback.apply(socket, args);
7
 						});
8
 					});
9
 

Jika tidak ada callback, kita dapat memanggil socket.emit ():

1
				} else {
2
 					socket.emit(event, data);
3
 				}
4
 			}
5
 

Penggunaan

Untuk menguji pustaka, kami akan membuat formulir sederhana yang akan mengirim beberapa data ke server dan menampilkan respons. Semua kode JavaScript ada di <script> tag di <head> dari dokumenmu dan semua HTML berada di <body> di dokumen Anda dan semua HTML masuk ke dalam -nya.

Membuat modul

Pertama kita harus membuat modul untuk aplikasi kita:

1
var app = angular.module('example', [ 'socket.io' ]);
2
 

Perhatikan bahwa 'socket.io' dalam larik, dalam parameter kedua, memberi tahu AngularJS bahwa modul ini bergantung pada pustaka Socket.IO.

Fungsi Konfigurasi

Karena kita akan menjalankan dari file HTML statis, kita harus menentukan URL koneksi untuk Socket.IO. Kita dapat melakukan ini menggunakan metode config() dari modul:

1
app.config(function ($socketProvider) {
2
 	$socketProvider.setConnectionUrl('http://localhost:8080');
3
 });
4
 

Seperti yang Anda lihat, $socketProvider kami secara otomatis disuntikkan oleh AngularJS.

Controller

Kontroler akan bertanggung jawab untuk semua logika aplikasi (aplikasi kecil, jadi kita hanya perlu satu):

1
app.controller('Ctrl', function Ctrl($scope, $socket) {
2
 

$scope adalah objek yang menampung semua model controller, ini adalah basis dari pengikatan data dua arah dari AngularJS. $socket adalah layanan Socket.IO kami.

Pertama, kita akan membuat pendengar untuk acara 'echo' yang akan dipancarkan oleh server pengujian kami:

1
	$socket.on('echo', function (data) {
2
 		$scope.serverResponse = data;
3
 	});
4
 

Kami akan menampilkan $ scope.serverResponse nanti, dalam HTML, menggunakan ekspresi AngularJS.

Sekarang juga akan ada dua fungsi yang akan mengirim data - satu menggunakan metode emit () dasar dan satu menggunakan emit () dengan callback pengakuan:

1
	$scope.emitBasic = function emitBasic() {
2
 		$socket.emit('echo', $scope.dataToSend);
3
 		$scope.dataToSend = '';
4
 	};
5
 
6
 	$scope.emitACK = function emitACK() {
7
 		$socket.emit('echo-ack', $scope.dataToSend, function (data) {
8
 			$scope.serverResponseACK = data;
9
 		});
10
 		$scope.dataToSend = '';
11
 	};
12
 });
13
 

Kita harus mendefinisikannya sebagai metode lingkup $scope sehingga kita dapat memanggil mereka dari direktif ngClick dalam HTML.

HTML

Di sinilah AngularJS bersinar - kita dapat menggunakan HTML standar dengan beberapa atribut khusus untuk mengikat semuanya bersama-sama.

Mari kita mulai dengan mendefinisikan modul utama menggunakan direktif ngApp. Tempatkan atribut ini di <body> tag dokumen anda

1
<body ng-app="example">
2
 

Ini memberitahu AngularJS bahwa seharusnya bootstrap aplikasi Anda menggunakan modul example.

Setelah itu, kita bisa membuat form dasar untuk mengirim data ke server:

1
	<div ng-controller="Ctrl">
2
 		<input ng-model="dataToSend">
3
 		<button ng-click="emitBasic()">Send</button>
4
 		<button ng-click="emitACK()">Send (ACK)</button>
5
 		<div>Server Response: {{ serverResponse }}</div>
6
 		<div>Server Response (ACK): {{ serverResponseACK }}</div>
7
 	</div>
8
 

Kami menggunakan beberapa atribut khusus dan arahan AngularJS di sana:

  • ng-controller - mengikat pengontrol yang ditentukan ke elemen ini, memungkinkan Anda menggunakan nilai dari cakupannya
  • ng-model - membuat data bi-directional mengikat antara elemen dan properti cakupan yang ditentukan (model), yang memungkinkan Anda untuk mendapatkan nilai dari elemen ini serta memodifikasi di dalam controller
  • ng-click - melampirkan listener kejadian clickyang mengeksekusi ekspresi tertentu (baca lebih lanjut tentang ekspresi AngularJS)

Tanda kurung kurawal ganda juga merupakan ekspresi AngularJS, mereka akan dievaluasi (jangan khawatir, tidak menggunakan  JavaScripteval ()) dan nilainya akan disisipkan di sana.

Jika Anda telah melakukan semuanya dengan benar, Anda harus dapat mengirim data ke server dengan mengklik tombol dan melihat respons dalam tag yang sesuai.


Dalam ringkasan

Di bagian pertama tutorial ini, kami telah membuat perpustakaan Socket.IO untuk AngularJS yang akan memungkinkan kami memanfaatkan WebSockets di aplikasi satu halaman kami. Di bagian kedua, saya akan menunjukkan kepada Anda bagaimana Anda dapat meningkatkan respon dari aplikasi Anda menggunakan kombinasi ini.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.