Nodejs Brown Bag

93
Intresserad av att jobba på Valtech? Kontakta vår rekryteringskoordinator [email protected] 070-165 34 83

description

Gabriel Falkenberg, konsult på Valtech, kommer på ett insiktsfullt och underhållande sätt berätta om lärdomar och upptäckter från sin resa med node.js. Sannolikt får vi se lite bra och/eller "intressant" kod också! "Jag försöker göra en brain dump av allt jag önskar jag hade vetat om Nodejs innan jag började."

Transcript of Nodejs Brown Bag

Page 1: Nodejs Brown Bag

Intresserad av att jobba på Valtech?!Kontakta vår rekryteringskoordinator!! [email protected]!! 070-165 34 83✉☎

Page 2: Nodejs Brown Bag

Gabriel Falkenberg

@gabriel_f

gabrielf

Jag heter Gabriel och jobbar här på Valtech och det senaste dryga året har jag jobbat på Viaplay med... node

Page 3: Nodejs Brown Bag

Jag misstänker att det finns lite olika förväntningar på den här presentationer. * Helt nya, vill lära sig grunderna * Vet lite men vill veta mer om styrkor och svagheter * Kan en hel del men vill snappa upp lite tips och tricks

Jag hoppas att de här 45 minuterna kommer innehålla lite för alla. Fokus är det jag tycker alla som utvecklar med Node ska känna till. Jag utgår från att alla kan javascript i viss mån.

Page 4: Nodejs Brown Bag

Ryan Dahl

På JSConf 2009 annonserade Ryan Dahl Node.js för första gången http://www.youtube.com/watch?v=ztspvPYybIY Han pratade om varför trådar är fel sätt att hantera samtidighet och att en event loop och asynkron I/O är ett bättre alternativ. Han bestämde sig för att se vad som hände om man lade en event loop och asynkron I/O ovanpå Javascript, kan det bli något användbart? Möt Node: Evented I/O for V8 javascript !

Page 5: Nodejs Brown Bag

Samtidighet

Resten

Samtidighet = Man måste förstå hur Node fungerar vad gäller asynkron I/O och händelseloopen för att bli en bra Node-utvecklare Resten = Lättviktighet, litet & enkelt standardbibiliotek, bra pakethantering, extremt aktivt community, draghjälp av javascript i frontend

Page 6: Nodejs Brown Bag

Java Node.js

Samtidighet

I en traditionell Java webbapp så serveras ett anrop av en tråd. Tråden har hand om anropet från början till slut. Det måste finnas en tråd per samtidigt anrop för att undvika att anrop hamnar på kö. !Uppenbara funderingar: * Hur är det möjligt? * Varför vill man göra så? * Varför gör inte alla så? * Vad är haken?

Page 7: Nodejs Brown Bag

Web Auth

SamtidighetDBPosta blogginlägg

Returnera HTML

Mycket kan hända i webbappen under ett anrop.

Page 8: Nodejs Brown Bag

Web

Java: Den nuvarande tråden väntar (andra kan jobbar vidare)

Node: Den enda tråden jobbare vidare med annat. Blir varskodd när det är möjligt att fortsätta.

Samtidighet

Skillnaden är här

Men mycket av det är väntetid. Jämför telefon vs. brev. Java ser operationerna som telefonsamtal, tråden väntar på svar Nodejs ser dem som brev och gör annat under tiden, agerar på brevet när det finns i brevlådan

Page 9: Nodejs Brown Bag

15 sekunder

10ms

Så kan en tråd hinna

17 dagar

100nsLäs från RAM-minne

Läs från databas

Läs från långsamt nätverk 300ms

Datortid Människotid

Läs från L1-cache 1ns

520 dagar

0,15 sekunder

En tråd som måste vänta på I/O är ungefär lika effektiv som en utvecklare som inte får jobba medan den inväntar svar på epost eller till och med fysiska brev... !Att köra på det sättet Node gör innebär att det totala jobbet delas i många små bitar. Detta kräver ett effektivt sätt att organisera många små jobb och det är där event-loopen kommer in.

Page 10: Nodejs Brown Bag

En event loopJobbkö

Det finns en kö med jobb att göra, det finns en tråd redo att göra jobbet. Jobben görs ett och ett och tråden kommer hela tiden plocka översta jobbet från kön när den är klar med det tidigare. När jobben är slut avslutas processen.

Page 11: Nodejs Brown Bag

En event loopJobbkö

Det finns en kö med jobb att göra, det finns en tråd redo att göra jobbet. Jobben görs ett och ett och tråden kommer hela tiden plocka översta jobbet från kön när den är klar med det tidigare. När jobben är slut avslutas processen.

Page 12: Nodejs Brown Bag

En event loopJobbkö

Det finns en kö med jobb att göra, det finns en tråd redo att göra jobbet. Jobben görs ett och ett och tråden kommer hela tiden plocka översta jobbet från kön när den är klar med det tidigare. När jobben är slut avslutas processen.

Page 13: Nodejs Brown Bag

En event loopJobbkö

Det finns en kö med jobb att göra, det finns en tråd redo att göra jobbet. Jobben görs ett och ett och tråden kommer hela tiden plocka översta jobbet från kön när den är klar med det tidigare. När jobben är slut avslutas processen.

Page 14: Nodejs Brown Bag

En event loopJobbkö

Men ett jobb kan också ge upphov till andra jobb. Tänk setTimeout(..., 0)

Page 15: Nodejs Brown Bag

En event loopJobbkö

Men vad är ett jobb? Jo en följd synkron kod tex. den först laddade filen. Det enklaste exemplet, ett Hello, World-program, är ett jobb i den här modellen.

Page 16: Nodejs Brown Bag

En event loopJobbkö

Men vad är ett jobb? Jo en följd synkron kod tex. den först laddade filen. Det enklaste exemplet, ett Hello, World-program, är ett jobb i den här modellen.

Page 17: Nodejs Brown Bag

En event loopJobbkö

Men vad är ett jobb? Jo en följd synkron kod tex. den först laddade filen. Det enklaste exemplet, ett Hello, World-program, är ett jobb i den här modellen.

Page 18: Nodejs Brown Bag

En event loopJobbkö

Men vad är ett jobb? Jo en följd synkron kod tex. den först laddade filen. Det enklaste exemplet, ett Hello, World-program, är ett jobb i den här modellen.

Page 19: Nodejs Brown Bag

En event loopJobbkö

Här är ett lite mer avancerat exempel där tre jobb figurerar. Det första kommer att skapa två andra jobb med hjälp av setTimeout som ni säkert känner igen från javascript i webbläsaren.

Page 20: Nodejs Brown Bag

En event loopJobbkö

Här är ett lite mer avancerat exempel där tre jobb figurerar. Det första kommer att skapa två andra jobb med hjälp av setTimeout som ni säkert känner igen från javascript i webbläsaren.

Page 21: Nodejs Brown Bag

En event loopJobbkö

Här är ett lite mer avancerat exempel där tre jobb figurerar. Det första kommer att skapa två andra jobb med hjälp av setTimeout som ni säkert känner igen från javascript i webbläsaren.

Page 22: Nodejs Brown Bag

En event loopJobbkö

Här är ett lite mer avancerat exempel där tre jobb figurerar. Det första kommer att skapa två andra jobb med hjälp av setTimeout som ni säkert känner igen från javascript i webbläsaren.

Page 23: Nodejs Brown Bag

En event loopJobbkö

Här är ett lite mer avancerat exempel där tre jobb figurerar. Det första kommer att skapa två andra jobb med hjälp av setTimeout som ni säkert känner igen från javascript i webbläsaren.

Page 24: Nodejs Brown Bag

En event loopJobbkö

Men ett jobb kan också ge upphov till andra jobb. Tänk setTimeout(..., 0)

Page 25: Nodejs Brown Bag

En event loopJobbkö

Men ett jobb kan också ge upphov till andra jobb. Tänk setTimeout(..., 0)

Page 26: Nodejs Brown Bag

En event loopJobbkö

Men ett jobb kan också ge upphov till andra jobb. Tänk setTimeout(..., 0)

Page 27: Nodejs Brown Bag

En event loopJobbkö

Men ett jobb kan också ge upphov till andra jobb. Tänk setTimeout(..., 0)

Page 28: Nodejs Brown Bag

En event loopJobbkö

Men det är förstås inte så här enkelt. Det finns också asynkrona operationer som inte direkt kan läggas till kön utan kan utföras först i framtiden. Vi kan säga att det är jobb som schemalagts.

Page 29: Nodejs Brown Bag

En event loopJobbköSchemaläggare

Men det är förstås inte så här enkelt. Det finns också asynkrona operationer som inte direkt kan läggas till kön utan kan utföras först i framtiden. Vi kan säga att det är jobb som schemalagts.

Page 30: Nodejs Brown Bag

En event loopJobbköSchemaläggare

Så när ett jobb körs så kan det inte bara hamna nya jobb på kön utan de kan också schemaläggas på lite olika sätt.

Page 31: Nodejs Brown Bag

En event loopJobbköSchemaläggare

Så när ett jobb körs så kan det inte bara hamna nya jobb på kön utan de kan också schemaläggas på lite olika sätt.

Page 32: Nodejs Brown Bag

En event loopJobbköSchemaläggare

Jobb som läggs på kön efter en viss tid, setTimeout(..., 100) Jobb som läggs på kön när en asynkron I/O operation är klar Och jobb som läggs på kön när något händer på nätverket

Page 33: Nodejs Brown Bag

En event loopJobbköSchemaläggare

Jobb som läggs på kön efter en viss tid, setTimeout(..., 100) Jobb som läggs på kön när en asynkron I/O operation är klar Och jobb som läggs på kön när något händer på nätverket

Page 34: Nodejs Brown Bag

En event loopJobbköSchemaläggare

Jobb som läggs på kön efter en viss tid, setTimeout(..., 100) Jobb som läggs på kön när en asynkron I/O operation är klar Och jobb som läggs på kön när något händer på nätverket

Page 35: Nodejs Brown Bag

En event loopJobbköSchemaläggare

Jobb som läggs på kön efter en viss tid, setTimeout(..., 100) Jobb som läggs på kön när en asynkron I/O operation är klar Och jobb som läggs på kön när något händer på nätverket

Page 36: Nodejs Brown Bag

En event loopJobbköSchemaläggare

Undertiden vår tråd väntar på de här jobben så finns de inte på kön men de kan hindra processen från att avslutas

Page 37: Nodejs Brown Bag

En event loopJobbköSchemaläggare

När tiden har gått så läggs jobbet på kön När filen lästs från disk så läggs jobbet på kön

Page 38: Nodejs Brown Bag

En event loopJobbköSchemaläggare

När tiden har gått så läggs jobbet på kön När filen lästs från disk så läggs jobbet på kön

Page 39: Nodejs Brown Bag

En event loopJobbköSchemaläggare

När tiden har gått så läggs jobbet på kön När filen lästs från disk så läggs jobbet på kön

Page 40: Nodejs Brown Bag

En event loopJobbköSchemaläggare

En öppen socket däremot kan ge upphov till en hel drös med jobb En extremt viktig aspekt av hur node fungerar är att ett jobb inte avbryts utifrån. Du kontrollerar när tråden kommer tillbaka till kön. Tänk kooperativ multikörning istället för preemptive. Du kan stöka till så mycket du vill så länge du städar efter dig. Farligt med Exceptions! Stäng av processen kontrollerat efter varje...

Page 41: Nodejs Brown Bag

En event loopJobbköSchemaläggare

En öppen socket däremot kan ge upphov till en hel drös med jobb En extremt viktig aspekt av hur node fungerar är att ett jobb inte avbryts utifrån. Du kontrollerar när tråden kommer tillbaka till kön. Tänk kooperativ multikörning istället för preemptive. Du kan stöka till så mycket du vill så länge du städar efter dig. Farligt med Exceptions! Stäng av processen kontrollerat efter varje...

Page 42: Nodejs Brown Bag

! Mindre minnesanvändning per anrop

! Enklare kod pga ingen multitrådning

! Inga lås leder till bra prestanda

! Bara ett sätt att skala

Fördelar och nackdelar med att jobba i en entrådad miljö. * Minnesanvändning är kanske inte ett problem för en vanlig webbserver kan blir det för websockets * Multitrådad programmering kan vara svårt: lås, deadlocks osv. * Kan vara långsamt att context-switcha mellan trådar, vänta på lås * Skala med processer istället för trådar och processer

Page 43: Nodejs Brown Bag

# Passar inte CPU-bundna problem

" Callback hell

* Callback hell. Att utveckla asynkront gör koden så komplicerad/ful att den är svår att hantera. * Asynkrona, händelsestyrda system liknar på sätt och vis ko-operativ multitasking, om ett varv i händelseloopen tar för lång tid får alla händelser på kö lida. while (true) {} hänger hela processen.

Page 44: Nodejs Brown Bag

$% Inge kul att hantera request-state

# Passar inte CPU-bundna problem

" Callback hell

* En tråd per anrop gör det enkelt att hantera request-state med thread-local storage. * Men! Continuation-local storage är en magisk modul som kan lösa det. Det används bland annat av new relics node plugin.

Page 45: Nodejs Brown Bag

Continuation-Local Storage$

# Passar inte CPU-bundna problem

" Callback hell

* En tråd per anrop gör det enkelt att hantera request-state med thread-local storage. * Men! Continuation-local storage är en magisk modul som kan lösa det. Det används bland annat av new relics node plugin.

Page 46: Nodejs Brown Bag

Continuation-Local Storage$

# Passar inte CPU-bundna problem

" Callback hell

* Det finns många webbramverk med asynkron I/O idag. Node är inte unikt och inte snabbare än andra språk! * I Nodejs är dock hela standardbiblioteket asynkront från start. Ryan valde Javascript då språket var anpassat för en tråd, men saknade standardbibliotek. * Googla på “read file java” och “read file node” och se skillnaden. * Det är svårare att göra fel av misstag

Page 47: Nodejs Brown Bag

Continuation-Local Storage$

# Passar inte CPU-bundna problem

Meh! Andra asynkrona

ramverk då?

" Callback hell

* Det finns många webbramverk med asynkron I/O idag. Node är inte unikt och inte snabbare än andra språk! * I Nodejs är dock hela standardbiblioteket asynkront från start. Ryan valde Javascript då språket var anpassat för en tråd, men saknade standardbibliotek. * Googla på “read file java” och “read file node” och se skillnaden. * Det är svårare att göra fel av misstag

Page 48: Nodejs Brown Bag
Page 49: Nodejs Brown Bag

Exempel på ett litet node-program. Intressanta saker är: console.log och setTimeout är inte en del av javascript utan liknar motsvarande funktioner i webbläsaren av bekvämlighet Processen stängs inte ner förrän setTimeout är klart. Men inte så kul om man inte kan inkludera funktionalitet från andra filer/moduler

Page 50: Nodejs Brown Bag

#!/usr/bin/env node

Kör med "node fil.js" eller med en shebang och ./fil.js

Page 51: Nodejs Brown Bag

Node implementerar CommonJS som är en spec för beroendehantering i javascript där saker inkluderas med require. Relativa eller absolute sökvägar för dina egna filer require är synkron! Cirkulära beroenden hanteras men med vissa begränsningar

Page 52: Nodejs Brown Bag

Även json-filer kan inkluderas

Page 53: Nodejs Brown Bag

Skriver du ingen filändelse inkludera i förstahand en js-fil och i andra hand en json-fil

Page 54: Nodejs Brown Bag

Inkluderar du en mapp kommer node leta efter en modul-beskrivning (package.json) och inkludera modulen huvud-fil och i andra hand index.js och tredje hand index.json

Page 55: Nodejs Brown Bag

Externa moduler inkluderas som ett enkelt namn och node kommer då att leta i ./node_modules och uppåt i trädet såvida det inte rör sig om en core-modul som har företräde !Men vad är det som jag importerar?

Page 56: Nodejs Brown Bag

Jo du importerar det som den andra filen/modulen exporterar i module.exports. module.exports är från början ett tomt objekt men här exporteras istället en sträng.

Page 57: Nodejs Brown Bag

Men du kan förstås exportera annat som funktioner eller objekt.

Page 58: Nodejs Brown Bag

Eller en klass. !Om exemplet kom från en enda fil skulle bara klassen exporteras eftersom det är vad module.exports innehåller till slut.

Page 59: Nodejs Brown Bag

Bara det i module.exports blir synligt. Inte det som i webbläsaren skulle vara globala variabler!

Page 60: Nodejs Brown Bag

Förutom om du glömmer var...

Page 61: Nodejs Brown Bag

Förändringar du gör av globala klasser syns överallt, var försiktig! !Det var en väldigt snabb introduktion till hur node-kod kan se ut. Läs dokumentationen.

Page 62: Nodejs Brown Bag

Dokumentation finns på http://nodejs.org/api och är föredömligt kort eftersom standardbiblioteket är så minimalt. Det tar troligtvis kortare tid att läsa genom all dokumentation här än att scrolla igenom all dokumentation om Javas standardbibliotek... Istället för ett enormt standardbibliotek finns...

Page 63: Nodejs Brown Bag

npm står för node package manager och är ett väldigt trevligt verktyg för allt möjligt som rör ett node-projekt. Allt från installera beroenden till att köra olika typer av test och bygg-script.

Page 64: Nodejs Brown Bag

{! "name": "my-lib",! "version": "0.0.0",! "main": "index.js",! "scripts": {! "test": "mocha"! },! "dependencies": {…}!}

Semantic Versioning

X.Y.ZMajor Minor Patch

main pekar ut den fil som exporteras från biblioteket eller som används för att starta applikationen. Versioner behandlas enligt semantik versioning semver.org Major = ej bakåtkompatibla ändringar, Minor = bakåtkompatibla tillägg, Patch = bakåtkompatibla buggfixar. Dock specialbehandlas versioner som börjar med 0, se npmjs.org/doc/misc/semver.html

Page 65: Nodejs Brown Bag

"dependencies": {! "async": "0.2.10",! "lodash": "^2.0.0",! "colors": "~0.6.0",!}

beroenden anges med version och kan vara exakta, kompatibla (enligt semver) eller ganska lika (patch-siffran kan öka). Använd kompatibel version (^) om du inte verkligen har anledning att tro att modulens förvaltare inte följer semver.

Page 66: Nodejs Brown Bag

npm init!npm install pkg [--save]!npm install pkg [--save-dev]!npm uninstall pkg [--save]!npm prune!npm ls

init: Skapa nytt projekt install: Installera beroende i node_modules, spara till package.json kan ange version med @version prune: Ta bort ur node_modules ls: Lista beroenden !

Page 67: Nodejs Brown Bag

npm test!npm run package-json-script!npm link!npm link pkg

test: Kör scripts.test från package.json run: Kör annat script definerat i package.json link: Skapa symlänkar till moduler under utveckling av diton

Page 68: Nodejs Brown Bag

npm shrinkwrap [--dev]

1.0.0^2.1.0 ?

npm hanterar beroenden transitivt. Ett beroende med ett versionsspann kan leda till olika versioner lokalt och i produktion när en ny version av beroendet släpps. Det ska fungera enligt semver men tänk på det finns problem i den nya versionen? Lösningen är npm shrinkwrap som tyvärr är förknippad med massa buggar... Du kan tex. inte styra längre om dev-beroenden ska installeras. Se github för issues.

Page 69: Nodejs Brown Bag

npm version patch!npm outdated!npm update pkg

version: Stega upp din moduls version, gör en git-commit/tag etc. outdated/update: Upptäck och öka versionen på dina beroenden Tips: Spana in modulers beroenden och moduler som personer du ser upp till skapar samt deras beroenden. Det är ett perfekt sätt att lära sig om nya moduler!

Page 70: Nodejs Brown Bag

Lägg!./node_modules/.bin/!

! i din PATH!

npm-moduler installeras som standard lokalt. Vissa moduler (grunt-cli, mocha) vill bli installerade globalt men gör inte det! Lägg istället ./node_modules/.bin/ i din PATH så slipper du eventuella versionskonflikter mellan dina Node-projekt.

Page 71: Nodejs Brown Bag

// package.json!!

"scripts": {! "test": "mocha && jshint",! "build": "grunt"!}

./node_modules/.bin/ finns redan i PATH för scripts. mocha, jshint och grunt ovan kommer i första hand köras från de lokalt installerade modulerna.

Page 72: Nodejs Brown Bag

Jag fick frågan en gång om det går att programmera Javascript utan att bli galen just med tanke på alla callbacks. !Innan vi går igenom strategier för att hantera callback-hell så ska vi dissekera en callback lite.

Page 73: Nodejs Brown Bag

Anatomin av en callback-funktion

Ett callback är en funktion som skickas till en annan funktion och anropas när den andra funktionen är klar, antingen på grund av fel eller eftersom den är färdig. För idiomatiska callbacks i node gäller: * Callbacken skickas sist i parameterlistan * Den kallas antingen med ett fel eller data eller inget, inte både och * Det kallas antingen synkront eller asynkront, aldrig en blandning

Page 74: Nodejs Brown Bag

Anatomin av en callback-funktion

forEach är ett exempel på kod som alltid körs synkront dvs. i exemplet ovan kommer utskriften bli: > före > i callback 1..3 > efter

Page 75: Nodejs Brown Bag

Anatomin av en callback-funktion

setTimeout kommer lägga callbacken på jobbkön så den körs som snabbast nästa varv genom händelseloopen (kanske ännu längre fram i tiden beroende på last) utskriften blir: > före > efter > i callback

Page 76: Nodejs Brown Bag

Möt callback hell

Det här är ett enkelt exempel, ett verkligt exempel skulle inte få plats på en sida. Men man ser den klassiska pyramid-formen även kallad "pyramid of doom". !Så hur hanterar man callback hell?

Page 77: Nodejs Brown Bag

Hantera callback hell

Diciplin + bibliotek

ES6 generators

Promises

Page 78: Nodejs Brown Bag

Hantera callback hell

Diciplin + bibliotek

Men man bör förstå första klassens funktioner, hur funktioner kan skapa andra funktioner, hur de kan skickas runt, hur de kan manipuleras med bind, hur de kan köras med call och apply. Vissa tycker sådana konstruktioner är för mycket magi men se till att alla utvecklare lär sig de här verktygen så kan koden bli mycket snyggare.

Page 79: Nodejs Brown Bag

Hantera callback hell

ES6 generators

ES6 = EcmaScript 6 = nästa version av Javascript. Aktivera när du kör "node --harmony fil.js". Just generatorer fungerar bara med Node 0.11 och högre.

Page 80: Nodejs Brown Bag

Hantera callback hell

Promises

Vanlig promiseskod. Dock inte alls optimal som jag fått lära mig av Jakob Mattson som skrivit ett promises-ramverk som heter z-core: https://github.com/jakobmattsson/z-core

Page 81: Nodejs Brown Bag

Hantera callback hell

Promises

Se: https://speakerdeck.com/jakobmattsson/how-to-star-actually-star-use-promises-in-javascript

Page 82: Nodejs Brown Bag

Vanliga fel

Page 83: Nodejs Brown Bag

Vanliga fel

Två fel, ingen return efter callback (absolut vanligaste felet!). Välj en kodstil som du tycker minskar risken att callbacken anropas två gånger !Ingen try/catch runt JSON.parse (nästan enda metoden i standardbiblioteket som kastar undantag, var uppmärksam!)

Page 84: Nodejs Brown Bag

Vanliga fel

Problem i try/catch. Om callback, som anropas synkront, kastar fel så fångas det här.

Page 85: Nodejs Brown Bag

Vanliga fel

Rätt kod, men ful. Du vill kanske extrahera JSON-parsning till en asynkron funktion som innehåller det fula try/catch-blocket.

Page 86: Nodejs Brown Bag

Vanliga fel

Här har vi förenklat fel-callbacken och vi använder oss av smidig js-syntax men det är fortfarande ett problem i koden. Om data finns i cachen så anropas callbacken synkront istället för asynkront. Gör inte det! Ändrar kör-ordningen i den kallande koden.

Page 87: Nodejs Brown Bag

Vanliga fel

Skillnaden här är hur callbacken anropas. Det finns tre sätt att schemalägga anrop av funktioner: setTimeout(..., 0), process.nextTick(...), setImmediate(...) Läs på om dessa! Om du inte orkar, använd alltid setImmediate.

Page 88: Nodejs Brown Bag

Vanliga fel

Node innehåller en extremt användbar interaktiv prompt. Men var försiktig om du använder lodash eller underscore eftersom "_" i prompten används för värdet av senaste uttrycket.

Page 89: Nodejs Brown Bag

Vanliga fel

Efter ett tag så skriver man callback-koden automatiskt och då kan det blir såhär. Koden i callbacken tillför i princip ingenting. Den kan förenklas till...

Page 90: Nodejs Brown Bag

Vanliga fel

...den här. Men tänk på att det bara gäller idiomatisk node-kod dvs. när man INTE får BÅDE err och data. I den här formen är det enkelt att se att callbacken inte tillför något alls och den kan tas bort...

Page 91: Nodejs Brown Bag

Vanliga fel

Och bli som exemplet ovan. Här är det uppenbart att doStuff inte tillför något heller...

Page 92: Nodejs Brown Bag

& Mellanhand, mycket I/O och väntan

% Problem där CPUn är flaskhalsen

' Många samtidiga anrop (websockets)

( Om du hatar Javascript

Page 93: Nodejs Brown Bag

The end

Bilder från!http://www.wpzoom.com!https://www.costumania.com/