Codarea Cabin Fever: Un tutorial back-end Node.js
Publicat: 2022-03-11Blocarea cauzată de COVID-19 îi ține pe mulți dintre noi blocați acasă, sperând, probabil, că simpla febră a cabinei este cel mai rău tip de febră pe care o vom experimenta. Mulți dintre noi consumăm mai mult conținut video decât oricând. În timp ce exercițiile fizice sunt deosebit de importante în acest moment, uneori, există nostalgie pentru luxul unei telecomenzi bune, de modă veche, atunci când laptopul nu este ușor de accesibil.
Aici intervine acest proiect: Oportunitatea de a transforma orice smartphone – chiar și unul vechi care altfel este inutil din lipsa actualizărilor – într-o telecomandă la îndemână pentru următorul Netflix/YouTube/Amazon Prime Video/etc. binge-watch. Este, de asemenea, un tutorial back-end Node.js: o șansă de a învăța elementele de bază ale JavaScript back-end folosind cadrul Express și motorul de șabloane Pug (fostul Jade).
Dacă acest lucru sună descurajant, proiectul Node.js complet va fi prezentat la sfârșit; cititorii trebuie să învețe doar atât cât sunt interesați să învețe și vor exista un număr destul de mare de explicații mai blânde ale unor elemente de bază pe care cititorii mai experimentați le pot sări peste.
De ce nu doar...?
Cititorii se pot întreba: „De ce să te apuci de codificarea unui back-end Node.js?” (Pe lângă oportunitatea de învățare, desigur.) „Nu există deja o aplicație pentru asta?”
Sigur, multe dintre ele. Dar există două motive majore pentru care acest lucru ar putea să nu fie de dorit:
- Pentru cei care încearcă să reutilizeze un telefon mai vechi, aceasta poate pur și simplu să nu mai fie o opțiune , așa cum este cazul dispozitivului Windows Phone 8.1 pe care am vrut să-l folosesc. (Magazinul de aplicații a fost închis oficial la sfârșitul anului 2019.)
- Încrederea (sau lipsa acesteia). La fel ca atâtea aplicații care se găsesc pe orice platformă mobilă, ele vin adesea cu cerința ca utilizatorii să acorde mult mai multe permisiuni decât are nevoie aplicația pentru ceea ce pretinde să facă. Dar chiar dacă acest aspect este limitat în mod corespunzător, natura unei aplicații de control de la distanță înseamnă că utilizatorii trebuie să aibă în continuare încredere că dezvoltatorii de aplicații nu abuzează de privilegiile lor la nivelul desktopului soluției prin includerea de programe spion sau alte programe malware.
Aceste probleme există de mult timp și au fost chiar motivația pentru un proiect similar din 2014 găsit pe GitHub. nvm
facilitează instalarea versiunilor mai vechi ale Node.js și, chiar dacă câteva dependențe au nevoie de upgrade, Node.js avea o reputație excelentă pentru a fi compatibil cu versiunea inversă.
Din păcate, bitrot a câștigat. O abordare obstinată și compatibilitatea back-end Node.js nu s-au potrivit pentru deprecieri nesfârșite și bucle de dependență imposibile între versiunile vechi ale Grunt, Bower și zeci de alte componente. Câteva ore mai târziu, era dincolo de clar că ar fi mult mai ușor să pornești de la zero – în ciuda sfatului acestui autor împotriva reinventării roții.
Gizmos noi de la vechi: reutilizarea telefoanelor ca telecomenzi folosind un back-end Node.js
În primul rând, rețineți că acest proiect Node.js este în prezent specific pentru Linux - dezvoltat și testat pe Linux Mint 19 și Linux Mint 19.3, în special - dar suportul pentru alte platforme ar putea fi adăugat cu siguranță. Este posibil să funcționeze deja pe un Mac.
Presupunând că este instalată o versiune modernă a Node.js și un prompt de comandă este deschis într-un director nou care va servi drept rădăcină a proiectului, suntem gata să începem cu Express:
npx express-generator --view=pug
Notă: Aici, npx
este un instrument la îndemână care vine cu npm
, managerul de pachete Node.js care este livrat cu Node.js. Îl folosim pentru a rula generatorul de schelet al aplicației Express. În momentul scrierii acestui articol, generatorul realizează un proiect Express/Node.js care, implicit, încă trage un motor de șablon numit Jade, chiar dacă proiectul Jade s-a redenumit în „Pug” de la versiunea 2.0 încolo. Așadar, pentru a fi la curent și a folosi Pug imediat - în plus, pentru a evita avertismentele de depreciere - vom --view=pug
, o opțiune de linie de comandă pentru script-ul express-generator
rulat de npx
.
Odată ce s-a terminat, trebuie să instalăm câteva pachete din lista de dependențe nou populată a proiectului nostru Node.js în package.json
. Modul tradițional de a face acest lucru este să rulați npm i
( i
pentru „instalare”). Dar unii încă preferă viteza lui Yarn, așa că dacă ai instalat asta, pur și simplu rulează yarn
fără parametri.
În acest caz, ar trebui să fie sigur să ignorați avertismentul de depreciere (sperăm că va fi remediat în curând) de la una dintre subdependențele lui Pug, atâta timp cât accesul este păstrat în funcție de necesități în rețeaua locală.
O pornire rapidă yarn start
npm start
, urmată de navigarea la localhost:3000
într-un browser, arată că back-end-ul nostru de bază Node.js bazat pe Express funcționează. Îl putem omorî cu Ctrl+C
.
Tutorial back-end Node.js, Pasul 2: Cum să trimiteți apăsările de taste pe mașina gazdă
Cu partea de telecomandă deja făcută la jumătate, să ne îndreptăm atenția către partea de control . Avem nevoie de ceva care să poată controla în mod programatic mașina pe care vom rula Node.js, pretinzând că apăsă tastele de pe tastatură.
Pentru asta, vom instala xdotool
folosind instrucțiunile sale oficiale. Un test rapid al exemplului lor de comandă într-un terminal:
xdotool search "Mozilla Firefox" windowactivate --sync key --clearmodifiers ctrl+l
… ar trebui să facă exact ce spune, presupunând că Mozilla Firefox este deschis la momentul respectiv. Asta e bine! Este ușor să facem ca proiectul nostru Node.js să apeleze instrumente de linie de comandă precum xdotool
, așa cum vom vedea în curând.
Tutorial back-end Node.js, Pasul 3: Designul caracteristicilor
Acest lucru poate să nu fie adevărat pentru toată lumea, dar personal, constat că multe telecomenzi fizice moderne au de aproximativ cinci ori mai multe butoane decât voi folosi vreodată. Deci, pentru acest proiect, ne uităm la un aspect pe ecran complet cu o grilă de trei câte trei de butoane frumoase, mari și ușor de vizat. Depinde de preferințele personale care ar putea fi acele nouă butoane.
Se pare că comenzile rapide de la tastatură chiar și pentru cele mai simple funcții nu sunt identice pe Netflix, YouTube și Amazon Prime Video. Nici aceste servicii nu funcționează cu chei media generice, așa cum este probabil să o facă o aplicație de redare muzicală nativă. De asemenea, este posibil ca anumite funcții să nu fie disponibile cu toate serviciile.
Deci, ceea ce va trebui să facem este să definim un aspect diferit al telecomenzii pentru fiecare serviciu și să oferim o modalitate de a comuta între ele.
Definirea aspectelor de control de la distanță și maparea lor cu comenzile rapide de la tastatură
Să obținem un prototip rapid care funcționează cu o mână de presetări. Le vom pune în common/preset_commands.js
— „common” deoarece vom include aceste date din mai multe fișiere:
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', }, }, };
Valorile codurilor cheie pot fi găsite folosind xev
. (Pentru mine, cele „audio mute” și „audio play” nu au fost descoperite folosind această metodă, așa că am consultat și o listă de taste media.)
Cititorii pot observa diferența de caz între space
și Return
— indiferent de motivul acestui lucru, acest detaliu trebuie respectat pentru ca xdotool
să funcționeze corect. Legat de aceasta, avem câteva definiții scrise în mod explicit - de exemplu, shift+p
chiar dacă P
ar funcționa și el - doar pentru a ne menține clare intențiile.
Tutorial back-end Node.js, Pasul 4: Punctul final „cheie” al API-ului nostru (Iertați jocul de cuvinte)
Vom avea nevoie de un punct final pentru POST
, care, la rândul său, va simula apăsările de taste folosind xdotool
. Deoarece vom avea diferite grupuri de chei pe care le putem trimite (una pentru fiecare serviciu), vom apela punctul final pentru un anumit group
. Vom reutiliza punctul final al users
generat prin redenumirea routes/users.js
în routes/group.js
și efectuând modificările corespunzătoare în app.js
:
// ... var indexRouter = require('./routes/index'); var groupRouter = require('./routes/group'); // ... app.use('/', indexRouter); app.use('/group', groupRouter); // ...
Funcționalitatea cheie este utilizarea xdotool
printr-un apel de shell de sistem în routes/group.js
. Vom codifica YouTube
ca meniu de alegere pentru moment, doar în scopuri de testare.
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;
Aici, luăm cheia solicitată „nume” din corpul solicitării POST
( req.body
) sub parametrul numit keystroke_name
. Va fi ceva de genul ️
. Apoi îl folosim pentru a căuta codul corespunzător din obiectul commands
preset_commands['YouTube']
.
Comanda finală este pe mai mult de o linie, astfel încât \
s de la sfârșitul fiecărei linii unește toate piesele într-o singură comandă:
-
search "YouTube"
preia prima fereastră cu „YouTube” în titlu. -
windowactivate --sync
activează fereastra preluată și așteaptă până când este gata să primească o apăsare de tastă. -
key --clearmodifiers ${keystroke_code}
trimite apăsarea tastei, asigurându-vă că ștergeți temporar tastele modificatoare, cum ar fi Caps Lock, care pot interfera cu ceea ce trimitem.
În acest moment, codul presupune că îi dăm input valid - ceva la care vom fi mai atenți mai târziu.
Pentru simplitate, codul va presupune, de asemenea, că există o singură fereastră de aplicație deschisă cu „YouTube” în titlu – dacă există mai multe potriviri, nu există nicio garanție că vom trimite apăsările de taste către fereastra dorită. Dacă aceasta este o problemă, poate fi de ajutor ca titlurile ferestrelor să poată fi schimbate pur și simplu schimbând filele browserului pe toate ferestrele, în afară de cea care urmează să fie controlată de la distanță.
Cu asta gata, putem porni serverul din nou, dar de data aceasta cu depanarea activată, astfel încât să putem vedea rezultatul apelurilor noastre de debug
. Pentru a face asta, pur și simplu rulați DEBUG=old-fashioned-remote:* yarn start
sau DEBUG=old-fashioned-remote:* npm start
. După ce rulează, redați un videoclip pe YouTube, deschideți o altă fereastră de terminal și încercați un apel cURL:
curl --data "keystroke_name=️" http://localhost:3000/group
Aceasta trimite o solicitare POST
cu numele de apăsare a tastei solicitat în corpul său către mașina noastră locală pe portul 3000
, portul pe care îl ascultă back-end-ul. Rularea acelei comenzi ar trebui să scoată note despre Executing
și Executed
în fereastra npm
și, mai important, să afișeze browserul și să-și întrerupă videoclipul. Executarea acelei comenzi din nou ar trebui să dea aceeași ieșire și să o anuleze.
Tutorial back-end Node.js, Pasul 5: Aspecte multiple de control de la distanță
Back-end-ul nostru nu este tocmai gata. De asemenea, vom avea nevoie de el pentru a putea:
- Produceți o listă de aspecte ale telecomenzii din
preset_commands
. - Produceți o listă de „nume” de taste după ce am ales un anumit aspect al telecomenzii. (De asemenea, am fi putut alege să folosim
common/preset_commands.js
direct pe front-end, deoarece este deja JavaScript, și am fi filtrat acolo. Acesta este unul dintre avantajele potențiale ale unui back-end Node.js, pur și simplu nu îl folosim aici .)
Ambele caracteristici sunt locul în care tutorialul nostru back-end Node.js se intersectează cu front-end-ul bazat pe Pug pe care îl vom construi.
Utilizarea șablonului Pug pentru a prezenta o listă de comenzi de la distanță
Partea back-end a ecuației înseamnă modificarea routes/index.js
pentru a arăta astfel:
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;
Aici, luăm numele de aspect al telecomenzii noastre ( group_names
) apelând Object.keys
din fișierul nostru preset_commands
. Apoi le trimitem și alte date de care vom avea nevoie către motorul de șabloane Pug, care este numit automat prin res.render()
.
Aveți grijă să nu confundați semnificația keys
aici cu tastele pe care le trimitem: Object.keys Object.keys
oferă o matrice (o listă ordonată) care conține toate cheile perechilor cheie-valoare care alcătuiesc un obiect în JavaScript:

const my_object = { 'a key' : 'its corresponding value' , 'another key' : 'its separate corresponding value' , };
Dacă ne uităm la common/preset_commands.js
, vom vedea modelul de mai sus, iar cheile noastre (în sensul obiectului) sunt numele grupurilor noastre: 'Netflix'
, 'YouTube'
etc. Valorile lor corespunzătoare nu sunt șiruri simple ca my_object
are mai sus - sunt obiecte întregi în sine, cu propriile chei, adică commands
și eventual window_name_override
.
CSS-ul personalizat transmis aici este, desigur, un pic de hack. Motivul pentru care avem nevoie de el în loc să folosim o soluție modernă, bazată pe flexbox, este pentru o mai bună compatibilitate cu lumea minunată a browserelor mobile în încarnările lor mai vechi și mai minunate. În acest caz, principalul lucru de reținut este că în modul peisaj, menținem butoanele mari, afișând nu mai mult de două opțiuni pe ecran; în modul portret, patru.
Dar unde se transformă de fapt în HTML pentru a fi trimis către browser? Aici intervine views/index.pug
, care vom dori să arate astfel:
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}
Prima linie este importantă: extends layout
înseamnă că Pug va prelua acest fișier în contextul views/layout.pug
, care este un fel de șablon părinte pe care îl vom reutiliza aici și, de asemenea, într-o altă vizualizare. Va trebui să adăugăm câteva rânduri după linia de link
, astfel încât fișierul final să arate astfel:
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
Nu vom intra în elementele de bază ale HTML aici, dar pentru cititorii care nu sunt familiarizați cu ele, acest cod Pug oglindește codul HTML cu tarif standard găsit aproape peste tot. Aspectul de șablon începe cu title= title
, care setează titlul HTML la orice valoare corespunzătoare cheii de title
a obiectului pe care îl transmitem Pug prin res.render
.
Putem vedea un aspect diferit al modelării a două linii mai târziu cu un block
pe care îl header_injection
. Blocurile ca acestea sunt substituenți care pot fi înlocuiți cu șabloane care îl extind pe cel curent. (Fără legătură, meta
-linia este pur și simplu o soluție rapidă pentru browserele mobile, așa că atunci când utilizatorii ating controlul volumului de mai multe ori la rând, telefonul se abține de la a mări sau micșora.)
Înapoi la block
noastre: Acesta este motivul pentru care views/index.pug
își definește propriile block
cu aceleași nume găsite în views/layout.pug
. În acest caz de header_injection
, aceasta ne permite să folosim CSS specific pentru orientările portret sau peisaj în care se va afla telefonul.
content
este locul unde punem partea principală vizibilă a paginii web, care în acest caz:
- Faceți bucle prin matricea
group_names
pe care o trecem, - creează un element
<span>
pentru fiecare cu clasa CSSgroup_bar
aplicată și - creează o legătură în fiecare
<span>
pe bazagroup_name
.
Clasa CSS group_bar
o putem defini în fișierul extras prin views/layout.pug
, și anume 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; }
În acest moment, dacă npm start
încă rulează, accesând http://localhost:3000/
într-un browser desktop ar trebui să arate două butoane foarte mari pentru Netflix și YouTube, restul fiind disponibil prin derularea în jos.
Dar dacă facem clic pe ele în acest moment, ele nu vor funcționa, pentru că nu am definit încă ruta la care se leagă (tingerea GET
a /group
.)
Se afișează aspectul ales al telecomenzii
Pentru a face acest lucru, vom adăuga acest lucru la routes/group.js
chiar înainte de linia finală module.exports
:
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` }); });
Acest lucru va primi numele grupului trimis la punctul final (de exemplu, punând ?group_name=Netflix
la sfârșitul /group/
), și îl va folosi pentru a obține valoarea commands
de la grupul corespunzător. Acea valoare ( group.commands
) este un obiect, iar cheile acelui obiect sunt numele ( keystroke_names
) pe care le vom afișa pe aspectul telecomenzii noastre.
Notă: dezvoltatorii neexperimentați nu vor trebui să intre în detalii despre modul în care funcționează, dar valoarea pentru title
folosește câteva expresii obișnuite pentru a transforma numele grupurilor/aspectului în acronime - de exemplu, telecomanda noastră YouTube va avea titlul browserului. YT-Remote
. În acest fel, dacă depanăm pe mașina noastră gazdă înainte de a încerca lucrurile pe un telefon, nu vom avea xdotool
să apuce fereastra browserului de telecomandă în sine, în loc de cea pe care încercăm să o controlăm. Între timp, pe telefoanele noastre, titlul va fi frumos și scurt, dacă vrem să marcam telecomandă.
Ca și în întâlnirea noastră anterioară cu res.render
, acesta își trimite datele pentru a se amesteca cu șablonul views/group.pug
. Vom crea acel fișier și îl vom completa cu asta:
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")
Ca și în cazul views/index.pug
, anulăm cele două bloguri din views/layout.pug
. De data aceasta, nu este vorba de CSS pe care îl punem în antet, ci de ceva JavaScript pe partea clientului, la care vom ajunge în curând. (Și da, într-un moment de persnicketism, am redenumit javascripts
incorect pluralizate...)
content
principal aici este un formular HTML format dintr-o mulțime de butoane de trimitere diferite, câte unul pentru fiecare keystroke_name
. Fiecare buton trimite formularul (efectuând o solicitare POST
) folosind numele apăsării tastei pe care îl afișează ca valoare pe care o trimite împreună cu formularul.
De asemenea, vom avea nevoie de puțin mai mult CSS în fișierul nostru principal de foaie de stil:
.remote_button { float: left; width: calc(100%/3); height: calc(100%/3); font-size: 12vh; }
Mai devreme, când am configurat punctul final, am terminat de tratat cererea cu:
return res.redirect(req.originalUrl);
Acest lucru înseamnă efectiv că atunci când browserul trimite formularul, back-end-ul Node.js răspunde spunând browserului să se întoarcă la pagina de la care a fost trimis formularul, adică, aspectul principal al telecomenzii. Ar fi mai elegant fără a schimba paginile; cu toate acestea, dorim compatibilitate maximă cu lumea ciudată și minunată a browserelor mobile decrepite. În acest fel, chiar și fără niciun JavaScript front-end să funcționeze, proiectul nostru back-end Node.js ar trebui să funcționeze în continuare.
O strop de JavaScript front-end
Dezavantajul utilizării unui formular pentru a trimite apăsările de taste este că browserul trebuie să aștepte și apoi să execute o călătorie dus-întors suplimentară: pagina și dependențele ei trebuie apoi solicitate din back-end-ul nostru Node.js și livrate. Apoi, acestea trebuie redate de browser.
Cititorii s-ar putea întreba cât de mult ar putea avea acest efect. La urma urmei, pagina este mică, dependențele sale sunt extrem de minime, iar proiectul nostru final Node.js va rula printr-o conexiune wifi locală. Ar trebui să fie o configurație cu latență scăzută, nu?
După cum se dovedește, cel puțin atunci când se testează pe smartphone-uri mai vechi care rulează Windows Phone 8.1 și Android 4.4.2, efectul este, din păcate, destul de vizibil în cazul obișnuit al atingerii rapide pentru a crește sau a reduce volumul de redare cu câteva crestături. Iată unde JavaScript poate ajuta, fără a ne îndepărta grațioasa noastră alternativă a POST
-urilor manuale prin formulare HTML.
În acest moment, JavaScript clientul nostru final (care va fi pus în public/javascript/group-client.js
) trebuie să fie compatibil cu browserele mobile vechi, care nu mai sunt acceptate. Dar nu avem nevoie de mult:
(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); } }); })();
Aici, funcția form_submit
doar trimite datele printr-un apel asincron, iar ultima linie împiedică comportamentul normal de trimitere al browserelor, prin care o nouă pagină se încarcă pe baza răspunsului serverului. A doua jumătate a acestui fragment așteaptă pur și simplu până când pagina se încarcă și apoi conectează fiecare buton de trimitere pentru a utiliza form_submit
. Totul este învelit într-un IIFE.
Atingeri finale
Există o serie de modificări la fragmentele de mai sus în versiunea finală a codului nostru tutorial back-end Node.js, mai ales în scopul unei mai bune gestionări a erorilor:
- Back-end-ul Node.js verifică acum numele grupurilor și apăsările de taste trimise pentru a se asigura că există. Acest cod se află într-o funcție care este reutilizată atât pentru funcțiile
GET
, cât și pentru funcțiilePOST
aleroutes/group.js
. - Folosim șablonul de
error
Pug dacă nu o fac. - JavaScript și CSS front-end fac acum butoanele să se contureze temporar în gri în timp ce se așteaptă un răspuns de la server, verzi de îndată ce semnalul a trecut prin
xdotool
și înapoi fără probleme și roșii dacă ceva nu a funcționat așa cum era de așteptat . - Backend-ul Node.js va tipări o urmă de stivă dacă moare, ceea ce va fi mai puțin probabil având în vedere cele de mai sus.
Cititorii sunt bineveniți să examineze (și/sau să cloneze) proiectul complet Node.js pe GitHub.
Tutorial back-end Node.js, Pasul 5: Un test în lumea reală
Este timpul să îl încercați pe un telefon real atașat la aceeași rețea wifi ca și gazda care rulează npm start
și un player de film sau muzică. Este doar o chestiune de a îndrepta browserul web al unui smartphone către adresa IP locală a gazdei (cu sufixul :3000
), care este probabil cel mai ușor de găsit rulând hostname -I | awk '{print $1}'
hostname -I | awk '{print $1}'
într-un terminal de pe gazdă.
O problemă pe care utilizatorii Windows Phone 8.1 o pot observa este că încercarea de a naviga la ceva de genul 192.168.2.5:3000
va da un pop-up de eroare:
Din fericire, nu trebuie să vă descurajați: pur și simplu introduceți prefixul cu http://
sau adăugați un final /
îl face să preia adresa fără alte plângeri.
Alegerea unei opțiuni acolo ar trebui să ne aducă la o telecomandă funcțională.
Pentru un plus de confort, utilizatorii pot dori să ajusteze setările DHCP ale routerului lor pentru a atribui întotdeauna aceeași adresă IP gazdei și să marcheze ecranul de selecție a aspectului și/sau orice aspect preferat.
Solicitări de tragere Bine ați venit
Este probabil că nu tuturor le va plăcea acest proiect așa cum este. Iată câteva idei de îmbunătățiri, pentru cei care doresc să aprofundeze codul:
- Ar trebui să fie simplu să modificați machetele sau să adăugați altele noi pentru alte servicii, cum ar fi Disney Plus.
- Poate că unii ar prefera un aspect „mod luminos” și opțiunea de a comuta între ele.
- Renunțarea la Netflix, deoarece este ireversibilă, ar putea folosi cu adevărat un „ești sigur?” o confirmare de vreun fel.
- Proiectul ar beneficia cu siguranță de suport Windows.
- Documentația lui
xdotool
menționează OSX - funcționează acest proiect (sau ar putea acest lucru) pe un Mac modern? - Pentru relaxare avansată, o modalitate de a căuta și de a naviga prin filme, în loc să fie nevoie să alegeți un singur film Netflix/Amazon Prime Video sau să creați o listă de redare YouTube de pe computer.
- O suită de testare automată, în cazul în care oricare dintre modificările sugerate încalcă funcționalitatea originală.
Sper că v-a plăcut acest tutorial back-end Node.js și ca rezultat o experiență media îmbunătățită. Streaming fericit – și codare!