Pengkodean Demam Kabin: Tutorial Back-end Node.js
Diterbitkan: 2022-03-11Penguncian COVID-19 membuat banyak dari kita terjebak di rumah, mungkin berharap bahwa demam kabin belaka adalah jenis demam terburuk yang akan kita alami. Banyak dari kita mengonsumsi lebih banyak konten video daripada sebelumnya. Meskipun olahraga sangat penting saat ini, terkadang, ada nostalgia akan kemewahan remote control kuno yang bagus saat laptop berada di luar jangkauan.
Di situlah proyek ini masuk: Peluang untuk mengubah ponsel cerdas apa pun—bahkan ponsel lama yang tidak berguna karena kurangnya pembaruan—menjadi remote praktis untuk Netflix/YouTube/Amazon Prime Video berikutnya/dll. menonton pesta. Ini juga merupakan tutorial back-end Node.js: kesempatan untuk mempelajari dasar-dasar JavaScript back-end menggunakan kerangka kerja Express dan mesin template Pug (sebelumnya Jade).
Jika itu terdengar menakutkan, proyek Node.js lengkap akan disajikan di akhir; pembaca hanya perlu belajar sebanyak mereka tertarik untuk belajar, dan akan ada cukup banyak penjelasan yang lebih lembut tentang beberapa dasar sepanjang jalan yang dapat dilewati oleh pembaca yang lebih berpengalaman.
Mengapa Tidak Hanya ...?
Pembaca mungkin bertanya-tanya, "Mengapa masuk ke pengkodean back end Node.js?" (Selain dari kesempatan belajar, tentu saja.) "Bukankah sudah ada aplikasi untuk itu?"
Tentu—banyak dari mereka. Tetapi ada dua alasan utama hal ini mungkin tidak diinginkan:
- Bagi mereka yang mencoba menggunakan kembali ponsel lama, ini mungkin bukan pilihan lagi , seperti halnya perangkat Windows Phone 8.1 yang ingin saya gunakan. (Toko aplikasi secara resmi ditutup pada akhir 2019.)
- Kepercayaan (atau kekurangannya). Seperti begitu banyak aplikasi yang dapat ditemukan di platform seluler apa pun, mereka sering kali datang dengan persyaratan pengguna memberikan izin yang jauh lebih banyak daripada yang dibutuhkan aplikasi untuk apa yang seharusnya dilakukan. Tetapi bahkan jika aspek ini dibatasi dengan tepat, sifat aplikasi kendali jarak jauh berarti bahwa pengguna masih harus percaya bahwa pengembang aplikasi tidak menyalahgunakan hak istimewa mereka di ujung desktop solusi dengan memasukkan spyware atau malware lainnya.
Masalah ini telah ada sejak lama dan bahkan menjadi motivasi untuk proyek serupa dari tahun 2014 yang ditemukan di GitHub. nvm
memudahkan penginstalan versi Node.js yang lebih lama, dan bahkan jika beberapa dependensi perlu ditingkatkan, Node.js memiliki reputasi yang baik karena kompatibel dengan versi sebelumnya.
Sayangnya, bitrot menang. Pendekatan keras kepala dan kompatibilitas back-end Node.js tidak cocok untuk penghentian tanpa akhir dan loop ketergantungan yang mustahil di antara versi lama Grunt, Bower, dan lusinan komponen lainnya. Beberapa jam kemudian, semakin jelas bahwa akan jauh lebih mudah untuk memulai dari awal—walaupun saran penulis ini sendiri untuk tidak menciptakan kembali roda.
Gizmos Baru dari Lama: Mengganti Ponsel sebagai Remote Control Menggunakan Node.js Back End
Pertama, perhatikan bahwa proyek Node.js ini saat ini khusus untuk Linux — dikembangkan dan diuji pada Linux Mint 19 dan Linux Mint 19.3, khususnya — tetapi dukungan untuk platform lain tentu saja dapat ditambahkan. Ini mungkin sudah berfungsi di Mac.
Dengan asumsi versi modern Node.js diinstal, dan prompt perintah terbuka di direktori baru yang akan berfungsi sebagai root proyek, kami siap untuk memulai dengan Express:
npx express-generator --view=pug
Catatan: Di sini, npx
adalah alat praktis yang disertakan dengan npm
, manajer paket Node.js yang dikirimkan bersama Node.js. Kami menggunakannya untuk menjalankan generator kerangka aplikasi Express. Pada tulisan ini, generator membuat proyek Express/Node.js yang, secara default, masih menggunakan mesin template yang disebut Jade, meskipun proyek Jade mengubah namanya menjadi "Pug" dari versi 2.0 dan seterusnya. Jadi untuk menjadi yang terkini dan langsung menggunakan Pug—plus, hindari peringatan penghentian—kami menggunakan --view=pug
, opsi baris perintah untuk skrip express-generator
yang dijalankan oleh npx
.
Setelah selesai, kita perlu menginstal beberapa paket dari daftar ketergantungan proyek Node.js yang baru diisi di package.json
. Cara tradisional untuk melakukan ini adalah dengan menjalankan npm i
( i
untuk "instal"). Tetapi beberapa masih lebih suka kecepatan Yarn, jadi jika Anda sudah menginstalnya, jalankan saja yarn
tanpa parameter.
Dalam hal ini, seharusnya aman untuk mengabaikan peringatan penghentian (semoga segera diperbaiki) dari salah satu sub-dependensi Pug, selama akses disimpan sesuai kebutuhan di jaringan lokal.
Sebuah yarn start
cepat atau npm start
, diikuti dengan menavigasi ke localhost:3000
di browser, menunjukkan bahwa back end Node.js berbasis Express dasar kami berfungsi. Kita bisa membunuhnya dengan Ctrl+C
.
Tutorial Back-end Node.js, Langkah 2: Cara Mengirim Keystrokes di Mesin Host
Dengan bagian remote yang sudah setengah jalan, mari kita alihkan perhatian kita ke bagian kontrol . Kita membutuhkan sesuatu yang secara terprogram dapat mengontrol mesin yang akan menjalankan back end Node.js kita, berpura-pura sedang menekan tombol pada keyboard.
Untuk itu, kami akan menginstal xdotool
menggunakan instruksi resminya. Tes cepat dari contoh perintah mereka di terminal:
xdotool search "Mozilla Firefox" windowactivate --sync key --clearmodifiers ctrl+l
…harus melakukan persis seperti yang dikatakan, dengan asumsi Mozilla Firefox terbuka pada saat itu. Bagus! Sangat mudah untuk membuat proyek Node.js kita memanggil alat baris perintah seperti xdotool
, seperti yang akan segera kita lihat.
Tutorial Back-end Node.js, Langkah 3: Desain Fitur
Ini mungkin tidak berlaku untuk semua orang, tetapi secara pribadi, saya menemukan bahwa banyak remote control fisik modern memiliki tombol sekitar lima kali lebih banyak daripada yang pernah saya gunakan. Jadi untuk proyek ini, kami melihat tata letak layar penuh dengan kisi tiga kali tiga tombol bagus, besar, dan mudah ditargetkan. Terserah preferensi pribadi apa sembilan tombol itu.
Ternyata pintasan keyboard untuk fungsi yang paling sederhana pun tidak identik di Netflix, YouTube, dan Amazon Prime Video. Layanan ini juga tidak berfungsi dengan kunci media generik seperti yang mungkin dilakukan oleh aplikasi pemutar musik asli. Selain itu, fungsi tertentu mungkin tidak tersedia dengan semua layanan.
Jadi yang perlu kita lakukan adalah menentukan tata letak kendali jarak jauh yang berbeda untuk setiap layanan dan menyediakan cara untuk beralih di antara mereka.
Mendefinisikan Tata Letak Remote Control dan Memetakannya ke Pintasan Keyboard
Mari kita membuat prototipe cepat bekerja dengan beberapa preset. Kami akan menempatkannya di common/preset_commands.js
—“common” karena kami akan menyertakan data ini dari lebih dari satu file:
module.exports = { // We could use ️ but some older phones (eg, Android 5.1.1) won't show it, hence ️ instead 'Netflix': { commands: { '-': 'Escape', '+': 'f', '': 'Up', '⇤': 'XF86Back', '️': 'Return', '': 'Down', '': 'Left', '': 'Right', '': 'm', }, }, 'YouTube': { commands: { '⇤': 'shift+p', '⇥': 'shift+n', '': 'Up', 'CC': 'c', '️': 'k', '': 'Down', '': 'j', '': 'l', '': 'm', }, }, 'Amazon Prime Video': { window_name_override: 'Prime Video', commands: { '⇤': 'Escape', '+': 'f', '': 'Up', 'CC': 'c', '️': 'space', '': 'Down', '': 'Left', '': 'Right', '': 'm', }, }, 'Generic / Music Player': { window_name_override: '', commands: { '⇤': 'XF86AudioPrev', '⇥': 'XF86AudioNext', '': 'XF86AudioRaiseVolume', '': 'r', '️': 'XF86AudioPlay', '': 'XF86AudioLowerVolume', '': 'Left', '': 'Right', '': 'XF86AudioMute', }, }, };
Nilai kode kunci dapat ditemukan menggunakan xev
. (Bagi saya, "audio mute" dan "audio play" tidak dapat ditemukan menggunakan metode ini, jadi saya juga melihat daftar kunci media.)
Pembaca mungkin melihat perbedaan antara space
dan Return
—terlepas dari alasannya, detail ini harus diperhatikan agar xdotool
berfungsi dengan benar. Terkait dengan ini, kami memiliki beberapa definisi yang ditulis secara eksplisit—misalnya, shift+p
meskipun P
juga akan berfungsi—hanya untuk menjaga niat kami tetap jelas.
Tutorial Back-end Node.js, Langkah 4: Titik Akhir “Kunci” API kami (Maafkan kesalahannya)
Kita memerlukan titik akhir untuk POST
, yang pada gilirannya akan mensimulasikan penekanan tombol menggunakan xdotool
. Karena kami akan memiliki grup kunci yang berbeda yang dapat kami kirim (satu untuk setiap layanan), kami akan memanggil titik akhir untuk satu group
tertentu . Kami akan menggunakan kembali titik akhir users
yang dihasilkan dengan mengganti nama routes/users.js
menjadi route routes/group.js
, dan membuat perubahan yang sesuai di app.js
:
// ... var indexRouter = require('./routes/index'); var groupRouter = require('./routes/group'); // ... app.use('/', indexRouter); app.use('/group', groupRouter); // ...
Fungsionalitas utamanya adalah menggunakan xdotool
melalui panggilan shell sistem di routes/group.js
. Kami akan mengkodekan YouTube
sebagai menu pilihan untuk saat ini, hanya untuk tujuan pengujian.
const express = require('express'); const router = express.Router(); const debug = require('debug')('app'); const cp = require('child_process'); const preset_commands = require('../common/preset_commands'); /* POST keystroke to simulate */ router.post('/', function(req, res, next) { const keystroke_name = req.body.keystroke_name; const keystroke_code = preset_commands['YouTube'].commands[keystroke_name]; const final_command = `xdotool \ search "YouTube" \ windowactivate --sync \ key --clearmodifiers ${keystroke_code}`; debug(`Executing ${final_command}`); cp.exec(final_command, (err, stdout, stderr) => { debug(`Executed ${keystroke_name}`); return res.redirect(req.originalUrl); }); }); module.exports = router;
Di sini, kami mengambil "nama" kunci yang diminta dari badan permintaan POST
( req.body
) di bawah parameter bernama keystroke_name
. Itu akan menjadi sesuatu seperti ️
. Kami kemudian menggunakannya untuk mencari kode yang sesuai dari objek commands
preset_commands['YouTube']
.
Perintah terakhir ada di lebih dari satu baris, jadi \
s di akhir setiap baris menggabungkan semua bagian menjadi satu perintah:
-
search "YouTube"
mengambil jendela pertama dengan judul "YouTube". -
windowactivate --sync
mengaktifkan jendela yang diambil dan menunggu hingga siap untuk menerima penekanan tombol. -
key --clearmodifiers ${keystroke_code}
mengirimkan penekanan tombol, memastikan untuk menghapus sementara tombol pengubah seperti Caps Lock yang dapat mengganggu apa yang kami kirim.
Pada titik ini, kode mengasumsikan bahwa kita memberinya input yang valid—sesuatu yang akan kita berhati-hati nanti.
Untuk mempermudah, kode juga akan mengasumsikan bahwa hanya ada satu jendela aplikasi yang terbuka dengan judul "YouTube"—jika ada lebih dari satu kecocokan, tidak ada jaminan kami akan mengirimkan penekanan tombol ke jendela yang dimaksud. Jika itu masalah, mungkin membantu bahwa judul jendela dapat diubah hanya dengan mengganti tab browser di semua jendela selain yang akan dikendalikan dari jarak jauh.
Dengan siap itu, kita dapat memulai server kita lagi, tetapi kali ini dengan debugging diaktifkan sehingga kita dapat melihat output dari panggilan debug
kita. Untuk melakukannya, jalankan DEBUG=old-fashioned-remote:* yarn start
atau DEBUG=old-fashioned-remote:* npm start
. Setelah dijalankan, putar video di YouTube, buka jendela terminal lain, dan coba panggilan cURL:
curl --data "keystroke_name=️" http://localhost:3000/group
Itu mengirimkan permintaan POST
dengan nama keystroke yang diminta di tubuhnya ke mesin lokal kami di port 3000
, port yang didengarkan oleh bagian belakang kami. Menjalankan perintah itu akan menampilkan catatan tentang Executing
dan Executed
di jendela npm
, dan yang lebih penting, buka browser dan jeda videonya. Menjalankan perintah itu lagi harus memberikan output yang sama dan membatalkan jeda.
Tutorial Back-end Node.js, Langkah 5: Beberapa Tata Letak Remote-control
Bagian belakang kami belum selesai. Kami juga membutuhkannya untuk dapat:
- Hasilkan daftar tata letak kendali jarak jauh dari
preset_commands
. - Buat daftar "nama" penekanan tombol setelah kami memilih tata letak kendali jarak jauh tertentu. (Kami juga bisa memilih untuk menggunakan
common/preset_commands.js
langsung di front end, karena itu sudah JavaScript, dan difilter di sana. Itulah salah satu keuntungan potensial dari back end Node.js, kami hanya tidak menggunakannya di sini .)
Kedua fitur ini adalah tempat tutorial back-end Node.js kami berpotongan dengan front end berbasis Pug yang akan kami buat.
Menggunakan Templat Pug untuk Menyajikan Daftar Kontrol Jarak Jauh
Bagian belakang persamaan berarti memodifikasi routes/index.js
agar terlihat seperti ini:
const express = require('express'); const router = express.Router(); const preset_commands = require('../common/preset_commands'); /* GET home page. */ router.get('/', function(req, res, next) { const group_names = Object.keys(preset_commands); res.render('index', { title: 'Which Remote?', group_names, portrait_css: `.group_bar { height: calc(100%/${Math.min(4, group_names.length)}); line-height: calc(100vh/${Math.min(4, group_names.length)}); }`, landscape_css: `.group_bar { height: calc(100%/${Math.min(2, group_names.length)}); line-height: calc(100vh/${Math.min(2, group_names.length)}); }`, }); }); module.exports = router;
Di sini, kami mengambil nama tata letak remote control kami ( group_names
) dengan memanggil Object.keys
pada file preset_commands
kami. Kami kemudian mengirimkannya dan beberapa data lain yang kami perlukan ke mesin template Pug yang secara otomatis dipanggil melalui res.render()
.
Berhati-hatilah untuk tidak mengacaukan arti keys
di sini dengan Object.keys
memberi kita sebuah larik (daftar terurut) yang berisi semua kunci dari pasangan nilai kunci yang membentuk sebuah objek dalam JavaScript:

const my_object = { 'a key' : 'its corresponding value' , 'another key' : 'its separate corresponding value' , };
Jika kita melihat common/preset_commands.js
, kita akan melihat pola di atas, dan kunci kita (dalam arti objek) adalah nama grup kita: 'Netflix'
, 'YouTube'
, dll. Nilai terkaitnya tidak string sederhana seperti yang dimiliki my_object
di atas—mereka adalah keseluruhan objek itu sendiri, dengan kuncinya sendiri, yaitu commands
dan mungkin window_name_override
.
CSS khusus yang diteruskan di sini, memang, sedikit diretas. Alasan kami membutuhkannya daripada menggunakan solusi modern berbasis flexbox adalah untuk kompatibilitas yang lebih baik dengan dunia browser seluler yang luar biasa dalam inkarnasi lama mereka yang bahkan lebih indah. Dalam hal ini, hal utama yang perlu diperhatikan adalah bahwa dalam mode lanskap, kami menjaga tombol tetap besar dengan menampilkan tidak lebih dari dua opsi per layar; dalam mode potret, empat.
Tapi di mana sebenarnya itu bisa diubah menjadi HTML untuk dikirim ke browser? Di situlah views/index.pug
masuk, yang kita ingin terlihat seperti ini:
extends layout block header_injection style(media='(orientation: portrait)') #{portrait_css} style(media='(orientation: landscape)') #{landscape_css} block content each group_name in group_names span(class="group_bar") a(href='/group/?group_name=' + group_name) #{group_name}
Baris pertama penting: extends layout
berarti Pug akan mengambil file ini dalam konteks views/layout.pug
, yang merupakan semacam templat induk yang akan kita gunakan kembali di sini dan juga di tampilan lain. Kita perlu menambahkan beberapa baris setelah baris link
sehingga file akhir terlihat seperti ini:
doctype html html head title= title link(rel='stylesheet', href='/stylesheets/style.css') block header_injection meta(name='viewport', content='user-scalable=no') body block content
Kami tidak akan masuk ke dasar-dasar HTML di sini, tetapi bagi pembaca yang tidak terbiasa dengannya, kode Pug ini mencerminkan kode HTML tarif standar yang ditemukan hampir di mana-mana. Aspek templatingnya dimulai dengan title= title
, yang menetapkan judul HTML ke nilai apa pun yang sesuai dengan kunci title
objek yang kita lewati Pug melalui res.render
.
Kita bisa melihat aspek berbeda dari templating dua baris nanti dengan block
yang kita beri nama header_injection
. Blok seperti ini adalah tempat penampung yang dapat diganti dengan templat yang memperpanjang yang sekarang. (Tidak terkait, garis meta
hanyalah solusi cepat untuk browser seluler, jadi ketika pengguna mengetuk kontrol volume beberapa kali berturut-turut, telepon menahan diri untuk memperbesar atau memperkecil.)
Kembali ke block
s kita: Inilah mengapa views/index.pug
mendefinisikan block
s-nya sendiri dengan nama yang sama yang ditemukan di views/layout.pug
. Dalam kasus header_injection
ini, ini memungkinkan kita menggunakan CSS khusus untuk orientasi potret atau lanskap yang akan digunakan ponsel.
content
adalah tempat kami meletakkan bagian utama yang terlihat dari halaman web, yang dalam hal ini:
- Loop melalui array
group_names
kita melewatinya, - membuat elemen
<span>
untuk masing-masing elemen dengan class CSSgroup_bar
yang diterapkan padanya, dan - membuat tautan di dalam setiap
<span>
berdasarkangroup_name
.
group_bar
kelas CSS dapat kita definisikan dalam file yang ditarik melalui views/layout.pug
, yaitu, public/stylesheets/style.css
:
html, body, form { padding: 0; margin: 0; height: 100%; font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; } .group_bar, .group_bar a, .remote_button { box-sizing: border-box; border: 1px solid white; color: greenyellow; background-color: black; } .group_bar { width: 100%; font-size: 6vh; text-align: center; display: inline-block; } .group_bar a { text-decoration: none; display: block; }
Pada titik ini, jika npm start
masih berjalan, membuka http://localhost:3000/
di browser desktop akan menampilkan dua tombol yang sangat besar untuk Netflix dan YouTube, dengan tombol lainnya tersedia dengan menggulir ke bawah.
Tetapi jika kita mengkliknya pada titik ini, mereka tidak akan berfungsi, karena kita belum menentukan rute yang mereka tautkan ( GET
ting dari /group
.)
Menampilkan Tata Letak Remote Control yang Dipilih
Untuk melakukannya, kami akan menambahkan ini ke routes/group.js
tepat sebelum baris module.exports
terakhir:
router.get('/', function(req, res, next) { const group_name = req.query.group_name || ''; const group = preset_commands[group_name]; return res.render('group', { keystroke_names: Object.keys(group.commands), group_name, title: `${group_name.match(/([AZ])/g).join('')}-Remote` }); });
Ini akan mendapatkan nama grup yang dikirim ke titik akhir (misalnya, dengan meletakkan ?group_name=Netflix
di akhir /group/
), dan menggunakannya untuk mendapatkan nilai commands
dari grup yang sesuai. Nilai tersebut ( group.commands
) adalah sebuah objek, dan kunci dari objek tersebut adalah nama ( keystroke_names
) yang akan kami tampilkan pada tata letak remote control kami.
Catatan: Pengembang yang tidak berpengalaman tidak perlu membahas detail cara kerjanya, tetapi nilai untuk title
menggunakan sedikit ekspresi reguler untuk mengubah nama grup/tata letak kami menjadi akronim—misalnya, remote YouTube kami akan memiliki judul browser YT-Remote
. Dengan begitu, jika kita melakukan debug pada mesin host kita sebelum mencoba berbagai hal di telepon, kita tidak akan memiliki xdotool
yang mengambil jendela browser kendali jarak jauh itu sendiri, alih-alih yang kita coba kendalikan. Sementara itu, di ponsel kita, judulnya akan bagus dan pendek, jika kita ingin mem-bookmark remote control.
Seperti pertemuan kita sebelumnya dengan res.render
, yang ini mengirimkan datanya untuk berbaur dengan template views/group.pug
. Kami akan membuat file itu dan mengisinya dengan ini:
extends layout block header_injection script(type='text/javascript', src='/javascript/group-client.js') block content form(action="/group?group_name=" + group_name, method="post") each keystroke_name in keystroke_names input(type="submit", name="keystroke_name", value=keystroke_name, class="remote_button")
Seperti views/index.pug
, kami mengganti kedua blog dari views/layout.pug
. Kali ini, bukan CSS yang kami masukkan ke dalam header, tetapi beberapa JavaScript sisi klien, yang akan segera kita bahas. (Dan ya, di saat-saat yang sulit, saya mengganti nama javascripts
yang salah plural ...)
content
utama di sini adalah formulir HTML yang terbuat dari sekumpulan tombol kirim yang berbeda, satu untuk setiap keystroke_name
. Setiap tombol mengirimkan formulir (membuat permintaan POST
) menggunakan nama penekanan tombol yang ditampilkan sebagai nilai yang dikirimkan bersama formulir.
Kami juga membutuhkan lebih banyak CSS di file stylesheet utama kami:
.remote_button { float: left; width: calc(100%/3); height: calc(100%/3); font-size: 12vh; }
Sebelumnya, ketika kami menyiapkan titik akhir, kami selesai menangani permintaan dengan:
return res.redirect(req.originalUrl);
Ini secara efektif berarti bahwa ketika browser mengirimkan formulir, bagian belakang Node.js merespons dengan memberi tahu browser untuk kembali ke halaman tempat formulir dikirimkan—yaitu, tata letak kendali jarak jauh utama. Akan lebih elegan tanpa berpindah halaman; namun, kami menginginkan kompatibilitas maksimum dengan dunia peramban seluler yang aneh dan menakjubkan. Dengan cara ini, bahkan tanpa JavaScript front-end yang berfungsi sama sekali, proyek back-end Node.js kami akan tetap berfungsi.
Sedikit JavaScript Front-end
Kelemahan menggunakan formulir untuk mengirimkan penekanan tombol adalah bahwa browser harus menunggu, dan kemudian melakukan perjalanan pulang pergi tambahan: Halaman dan dependensinya kemudian harus diminta dari back end Node.js kami dan dikirimkan. Kemudian, mereka perlu dirender lagi oleh browser.
Pembaca mungkin bertanya-tanya seberapa besar pengaruhnya. Lagi pula, halamannya kecil, ketergantungannya sangat minim, dan proyek Node.js terakhir kami akan berjalan melalui koneksi wifi lokal. Seharusnya pengaturan latensi rendah, bukan?
Ternyata—setidaknya saat menguji pada ponsel cerdas lama yang menjalankan Windows Phone 8.1 dan Android 4.4.2—efeknya sayangnya cukup terlihat dalam kasus umum mengetuk cepat untuk menaikkan atau menurunkan volume pemutaran beberapa takik. Di sinilah JavaScript dapat membantu, tanpa menghilangkan fallback manual POST
kami yang anggun melalui formulir HTML.
Pada titik ini, JavaScript klien terakhir kami (untuk diletakkan di public/javascript/group-client.js
) harus kompatibel dengan browser seluler lama yang tidak lagi didukung. Tapi kita tidak membutuhkan banyak:
(function () { function form_submit(event) { var request = new XMLHttpRequest(); request.open('POST', window.location.pathname + window.location.search, true); request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); request.send('keystroke_name=' + encodeURIComponent(event.target.value)); event.preventDefault(); } window.addEventListener("DOMContentLoaded", function() { var inputs = document.querySelectorAll("input"); for (var i = 0; i < inputs.length; i++) { inputs[i].addEventListener("click", form_submit); } }); })();
Di sini, fungsi form_submit
hanya mengirim data melalui panggilan asinkron, dan baris terakhir mencegah perilaku pengiriman normal browser, di mana halaman baru dimuat berdasarkan respons server. Bagian terakhir dari cuplikan ini hanya menunggu hingga halaman dimuat dan kemudian menghubungkan setiap tombol kirim untuk menggunakan form_submit
. Semuanya dibungkus dalam IIFE.
Sentuhan Akhir
Ada sejumlah perubahan pada cuplikan di atas dalam versi final kode tutorial back-end Node.js kami, sebagian besar untuk tujuan penanganan kesalahan yang lebih baik:
- Bagian belakang Node.js sekarang memeriksa nama grup dan penekanan tombol yang dikirim ke sana untuk memastikan mereka ada. Kode ini ada dalam fungsi yang digunakan kembali untuk fungsi
GET
danPOST
dariroutes/group.js
. - Kami menggunakan template
error
Pug jika tidak. - JavaScript dan CSS front-end sekarang membuat tombol sementara digariskan dalam warna abu-abu sambil menunggu tanggapan dari server, hijau segera setelah sinyal melewati
xdotool
dan kembali tanpa masalah, dan merah jika ada yang tidak berfungsi seperti yang diharapkan . - Bagian belakang Node.js akan mencetak jejak tumpukan jika mati, yang kemungkinan kecil akan diberikan di atas.
Pembaca dipersilakan untuk membaca dengan teliti (dan/atau mengkloning) proyek Node.js lengkap di GitHub.
Tutorial Back-end Node.js, Langkah 5: Tes Dunia Nyata
Saatnya untuk mencobanya di ponsel sebenarnya yang terhubung ke jaringan wifi yang sama dengan host yang menjalankan npm start
dan pemutar film atau musik. Ini hanya masalah mengarahkan browser web ponsel cerdas ke alamat IP lokal host (dengan akhiran :3000
), yang mungkin paling mudah ditemukan dengan menjalankan hostname -I | awk '{print $1}'
hostname -I | awk '{print $1}'
di terminal pada Host.
Satu masalah yang mungkin diperhatikan oleh pengguna Windows Phone 8.1 adalah mencoba menavigasi ke sesuatu seperti 192.168.2.5:3000
akan memberikan sembulan kesalahan:
Untungnya, tidak perlu berkecil hati: Cukup awali dengan http://
atau tambahkan trailing /
dapatkan untuk mengambil alamat tanpa keluhan lebih lanjut.
Memilih opsi di sana akan membawa kita ke remote control yang berfungsi.
Untuk menambah kenyamanan, pengguna mungkin ingin menyesuaikan pengaturan DHCP router mereka untuk selalu menetapkan alamat IP yang sama ke host, dan menandai layar pemilihan tata letak dan/atau tata letak favorit apa pun.
Permintaan Tarik Selamat datang
Sepertinya tidak semua orang akan menyukai proyek ini sebagaimana adanya. Berikut adalah beberapa ide untuk perbaikan, bagi mereka yang ingin menggali lebih jauh ke dalam kode:
- Seharusnya mudah untuk mengubah tata letak atau menambahkan yang baru untuk layanan lain, seperti Disney Plus.
- Mungkin beberapa lebih suka tata letak "mode ringan" dan opsi untuk beralih di antara keduanya.
- Mundur dari Netflix, karena tidak dapat dibalik, benar-benar dapat menggunakan pertanyaan "apakah Anda yakin?" semacam konfirmasi.
- Proyek ini pasti akan mendapat manfaat dari dukungan Windows.
-
xdotool
memang menyebutkan OSX—apakah proyek ini (atau dapatkah ini) bekerja pada Mac modern? - Untuk bersantai tingkat lanjut, cara untuk mencari dan menelusuri film, daripada harus memilih satu film Netflix/Amazon Prime Video atau membuat daftar putar YouTube di komputer.
- Rangkaian pengujian otomatis, jika ada perubahan yang disarankan yang merusak fungsi aslinya.
Saya harap Anda menikmati tutorial back-end Node.js ini dan sebagai hasilnya, pengalaman media yang lebih baik. Selamat streaming—dan coding!