├── LICENSE └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | Attribution-ShareAlike 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More_considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution-ShareAlike 4.0 International Public 58 | License 59 | 60 | By exercising the Licensed Rights (defined below), You accept and agree 61 | to be bound by the terms and conditions of this Creative Commons 62 | Attribution-ShareAlike 4.0 International Public License ("Public 63 | License"). To the extent this Public License may be interpreted as a 64 | contract, You are granted the Licensed Rights in consideration of Your 65 | acceptance of these terms and conditions, and the Licensor grants You 66 | such rights in consideration of benefits the Licensor receives from 67 | making the Licensed Material available under these terms and 68 | conditions. 69 | 70 | 71 | Section 1 -- Definitions. 72 | 73 | a. Adapted Material means material subject to Copyright and Similar 74 | Rights that is derived from or based upon the Licensed Material 75 | and in which the Licensed Material is translated, altered, 76 | arranged, transformed, or otherwise modified in a manner requiring 77 | permission under the Copyright and Similar Rights held by the 78 | Licensor. For purposes of this Public License, where the Licensed 79 | Material is a musical work, performance, or sound recording, 80 | Adapted Material is always produced where the Licensed Material is 81 | synched in timed relation with a moving image. 82 | 83 | b. Adapter's License means the license You apply to Your Copyright 84 | and Similar Rights in Your contributions to Adapted Material in 85 | accordance with the terms and conditions of this Public License. 86 | 87 | c. BY-SA Compatible License means a license listed at 88 | creativecommons.org/compatiblelicenses, approved by Creative 89 | Commons as essentially the equivalent of this Public License. 90 | 91 | d. Copyright and Similar Rights means copyright and/or similar rights 92 | closely related to copyright including, without limitation, 93 | performance, broadcast, sound recording, and Sui Generis Database 94 | Rights, without regard to how the rights are labeled or 95 | categorized. For purposes of this Public License, the rights 96 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 97 | Rights. 98 | 99 | e. Effective Technological Measures means those measures that, in the 100 | absence of proper authority, may not be circumvented under laws 101 | fulfilling obligations under Article 11 of the WIPO Copyright 102 | Treaty adopted on December 20, 1996, and/or similar international 103 | agreements. 104 | 105 | f. Exceptions and Limitations means fair use, fair dealing, and/or 106 | any other exception or limitation to Copyright and Similar Rights 107 | that applies to Your use of the Licensed Material. 108 | 109 | g. License Elements means the license attributes listed in the name 110 | of a Creative Commons Public License. The License Elements of this 111 | Public License are Attribution and ShareAlike. 112 | 113 | h. Licensed Material means the artistic or literary work, database, 114 | or other material to which the Licensor applied this Public 115 | License. 116 | 117 | i. Licensed Rights means the rights granted to You subject to the 118 | terms and conditions of this Public License, which are limited to 119 | all Copyright and Similar Rights that apply to Your use of the 120 | Licensed Material and that the Licensor has authority to license. 121 | 122 | j. Licensor means the individual(s) or entity(ies) granting rights 123 | under this Public License. 124 | 125 | k. Share means to provide material to the public by any means or 126 | process that requires permission under the Licensed Rights, such 127 | as reproduction, public display, public performance, distribution, 128 | dissemination, communication, or importation, and to make material 129 | available to the public including in ways that members of the 130 | public may access the material from a place and at a time 131 | individually chosen by them. 132 | 133 | l. Sui Generis Database Rights means rights other than copyright 134 | resulting from Directive 96/9/EC of the European Parliament and of 135 | the Council of 11 March 1996 on the legal protection of databases, 136 | as amended and/or succeeded, as well as other essentially 137 | equivalent rights anywhere in the world. 138 | 139 | m. You means the individual or entity exercising the Licensed Rights 140 | under this Public License. Your has a corresponding meaning. 141 | 142 | 143 | Section 2 -- Scope. 144 | 145 | a. License grant. 146 | 147 | 1. Subject to the terms and conditions of this Public License, 148 | the Licensor hereby grants You a worldwide, royalty-free, 149 | non-sublicensable, non-exclusive, irrevocable license to 150 | exercise the Licensed Rights in the Licensed Material to: 151 | 152 | a. reproduce and Share the Licensed Material, in whole or 153 | in part; and 154 | 155 | b. produce, reproduce, and Share Adapted Material. 156 | 157 | 2. Exceptions and Limitations. For the avoidance of doubt, where 158 | Exceptions and Limitations apply to Your use, this Public 159 | License does not apply, and You do not need to comply with 160 | its terms and conditions. 161 | 162 | 3. Term. The term of this Public License is specified in Section 163 | 6(a). 164 | 165 | 4. Media and formats; technical modifications allowed. The 166 | Licensor authorizes You to exercise the Licensed Rights in 167 | all media and formats whether now known or hereafter created, 168 | and to make technical modifications necessary to do so. The 169 | Licensor waives and/or agrees not to assert any right or 170 | authority to forbid You from making technical modifications 171 | necessary to exercise the Licensed Rights, including 172 | technical modifications necessary to circumvent Effective 173 | Technological Measures. For purposes of this Public License, 174 | simply making modifications authorized by this Section 2(a) 175 | (4) never produces Adapted Material. 176 | 177 | 5. Downstream recipients. 178 | 179 | a. Offer from the Licensor -- Licensed Material. Every 180 | recipient of the Licensed Material automatically 181 | receives an offer from the Licensor to exercise the 182 | Licensed Rights under the terms and conditions of this 183 | Public License. 184 | 185 | b. Additional offer from the Licensor -- Adapted Material. 186 | Every recipient of Adapted Material from You 187 | automatically receives an offer from the Licensor to 188 | exercise the Licensed Rights in the Adapted Material 189 | under the conditions of the Adapter's License You apply. 190 | 191 | c. No downstream restrictions. You may not offer or impose 192 | any additional or different terms or conditions on, or 193 | apply any Effective Technological Measures to, the 194 | Licensed Material if doing so restricts exercise of the 195 | Licensed Rights by any recipient of the Licensed 196 | Material. 197 | 198 | 6. No endorsement. Nothing in this Public License constitutes or 199 | may be construed as permission to assert or imply that You 200 | are, or that Your use of the Licensed Material is, connected 201 | with, or sponsored, endorsed, or granted official status by, 202 | the Licensor or others designated to receive attribution as 203 | provided in Section 3(a)(1)(A)(i). 204 | 205 | b. Other rights. 206 | 207 | 1. Moral rights, such as the right of integrity, are not 208 | licensed under this Public License, nor are publicity, 209 | privacy, and/or other similar personality rights; however, to 210 | the extent possible, the Licensor waives and/or agrees not to 211 | assert any such rights held by the Licensor to the limited 212 | extent necessary to allow You to exercise the Licensed 213 | Rights, but not otherwise. 214 | 215 | 2. Patent and trademark rights are not licensed under this 216 | Public License. 217 | 218 | 3. To the extent possible, the Licensor waives any right to 219 | collect royalties from You for the exercise of the Licensed 220 | Rights, whether directly or through a collecting society 221 | under any voluntary or waivable statutory or compulsory 222 | licensing scheme. In all other cases the Licensor expressly 223 | reserves any right to collect such royalties. 224 | 225 | 226 | Section 3 -- License Conditions. 227 | 228 | Your exercise of the Licensed Rights is expressly made subject to the 229 | following conditions. 230 | 231 | a. Attribution. 232 | 233 | 1. If You Share the Licensed Material (including in modified 234 | form), You must: 235 | 236 | a. retain the following if it is supplied by the Licensor 237 | with the Licensed Material: 238 | 239 | i. identification of the creator(s) of the Licensed 240 | Material and any others designated to receive 241 | attribution, in any reasonable manner requested by 242 | the Licensor (including by pseudonym if 243 | designated); 244 | 245 | ii. a copyright notice; 246 | 247 | iii. a notice that refers to this Public License; 248 | 249 | iv. a notice that refers to the disclaimer of 250 | warranties; 251 | 252 | v. a URI or hyperlink to the Licensed Material to the 253 | extent reasonably practicable; 254 | 255 | b. indicate if You modified the Licensed Material and 256 | retain an indication of any previous modifications; and 257 | 258 | c. indicate the Licensed Material is licensed under this 259 | Public License, and include the text of, or the URI or 260 | hyperlink to, this Public License. 261 | 262 | 2. You may satisfy the conditions in Section 3(a)(1) in any 263 | reasonable manner based on the medium, means, and context in 264 | which You Share the Licensed Material. For example, it may be 265 | reasonable to satisfy the conditions by providing a URI or 266 | hyperlink to a resource that includes the required 267 | information. 268 | 269 | 3. If requested by the Licensor, You must remove any of the 270 | information required by Section 3(a)(1)(A) to the extent 271 | reasonably practicable. 272 | 273 | b. ShareAlike. 274 | 275 | In addition to the conditions in Section 3(a), if You Share 276 | Adapted Material You produce, the following conditions also apply. 277 | 278 | 1. The Adapter's License You apply must be a Creative Commons 279 | license with the same License Elements, this version or 280 | later, or a BY-SA Compatible License. 281 | 282 | 2. You must include the text of, or the URI or hyperlink to, the 283 | Adapter's License You apply. You may satisfy this condition 284 | in any reasonable manner based on the medium, means, and 285 | context in which You Share Adapted Material. 286 | 287 | 3. You may not offer or impose any additional or different terms 288 | or conditions on, or apply any Effective Technological 289 | Measures to, Adapted Material that restrict exercise of the 290 | rights granted under the Adapter's License You apply. 291 | 292 | 293 | Section 4 -- Sui Generis Database Rights. 294 | 295 | Where the Licensed Rights include Sui Generis Database Rights that 296 | apply to Your use of the Licensed Material: 297 | 298 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 299 | to extract, reuse, reproduce, and Share all or a substantial 300 | portion of the contents of the database; 301 | 302 | b. if You include all or a substantial portion of the database 303 | contents in a database in which You have Sui Generis Database 304 | Rights, then the database in which You have Sui Generis Database 305 | Rights (but not its individual contents) is Adapted Material, 306 | 307 | including for purposes of Section 3(b); and 308 | c. You must comply with the conditions in Section 3(a) if You Share 309 | all or a substantial portion of the contents of the database. 310 | 311 | For the avoidance of doubt, this Section 4 supplements and does not 312 | replace Your obligations under this Public License where the Licensed 313 | Rights include other Copyright and Similar Rights. 314 | 315 | 316 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 317 | 318 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 319 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 320 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 321 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 322 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 323 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 324 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 325 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 326 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 327 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 328 | 329 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 330 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 331 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 332 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 333 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 334 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 335 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 336 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 337 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 338 | 339 | c. The disclaimer of warranties and limitation of liability provided 340 | above shall be interpreted in a manner that, to the extent 341 | possible, most closely approximates an absolute disclaimer and 342 | waiver of all liability. 343 | 344 | 345 | Section 6 -- Term and Termination. 346 | 347 | a. This Public License applies for the term of the Copyright and 348 | Similar Rights licensed here. However, if You fail to comply with 349 | this Public License, then Your rights under this Public License 350 | terminate automatically. 351 | 352 | b. Where Your right to use the Licensed Material has terminated under 353 | Section 6(a), it reinstates: 354 | 355 | 1. automatically as of the date the violation is cured, provided 356 | it is cured within 30 days of Your discovery of the 357 | violation; or 358 | 359 | 2. upon express reinstatement by the Licensor. 360 | 361 | For the avoidance of doubt, this Section 6(b) does not affect any 362 | right the Licensor may have to seek remedies for Your violations 363 | of this Public License. 364 | 365 | c. For the avoidance of doubt, the Licensor may also offer the 366 | Licensed Material under separate terms or conditions or stop 367 | distributing the Licensed Material at any time; however, doing so 368 | will not terminate this Public License. 369 | 370 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 371 | License. 372 | 373 | 374 | Section 7 -- Other Terms and Conditions. 375 | 376 | a. The Licensor shall not be bound by any additional or different 377 | terms or conditions communicated by You unless expressly agreed. 378 | 379 | b. Any arrangements, understandings, or agreements regarding the 380 | Licensed Material not stated herein are separate from and 381 | independent of the terms and conditions of this Public License. 382 | 383 | 384 | Section 8 -- Interpretation. 385 | 386 | a. For the avoidance of doubt, this Public License does not, and 387 | shall not be interpreted to, reduce, limit, restrict, or impose 388 | conditions on any use of the Licensed Material that could lawfully 389 | be made without permission under this Public License. 390 | 391 | b. To the extent possible, if any provision of this Public License is 392 | deemed unenforceable, it shall be automatically reformed to the 393 | minimum extent necessary to make it enforceable. If the provision 394 | cannot be reformed, it shall be severed from this Public License 395 | without affecting the enforceability of the remaining terms and 396 | conditions. 397 | 398 | c. No term or condition of this Public License will be waived and no 399 | failure to comply consented to unless expressly agreed to by the 400 | Licensor. 401 | 402 | d. Nothing in this Public License constitutes or may be interpreted 403 | as a limitation upon, or waiver of, any privileges and immunities 404 | that apply to the Licensor or You, including from the legal 405 | processes of any jurisdiction or authority. 406 | 407 | 408 | ======================================================================= 409 | 410 | Creative Commons is not a party to its public 411 | licenses. Notwithstanding, Creative Commons may elect to apply one of 412 | its public licenses to material it publishes and in those instances 413 | will be considered the “Licensor.” The text of the Creative Commons 414 | public licenses is dedicated to the public domain under the CC0 Public 415 | Domain Dedication. Except for the limited purpose of indicating that 416 | material is shared under a Creative Commons public license or as 417 | otherwise permitted by the Creative Commons policies published at 418 | creativecommons.org/policies, Creative Commons does not authorize the 419 | use of the trademark "Creative Commons" or any other trademark or logo 420 | of Creative Commons without its prior written consent including, 421 | without limitation, in connection with any unauthorized modifications 422 | to any of its public licenses or any other arrangements, 423 | understandings, or agreements concerning use of licensed material. For 424 | the avoidance of doubt, this paragraph does not form part of the 425 | public licenses. 426 | 427 | Creative Commons may be contacted at creativecommons.org. 428 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Fondamentali di Node.js [![This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.](https://i.creativecommons.org/l/by-sa/4.0/88x31.png)](https://creativecommons.org/licenses/by-sa/4.0/) 2 | 3 | >⚠️ ⚠️ ⚠️ 4 | > 5 | >Questo documento è stato scritto qualche anno fa e non è pertanto aggiornato con le ultime evoluzioni di JavaScript e relative best practice. È ancora valido come introduzione leggera a JavaScript ma alcune cose sono superate. Anche il libro menzionato in fondo per alcuni aspetti non è più attuale e la seconda edizione non è ancora completa. 6 | > 7 | >Se qualcuno prenderà questo documento come riferimento, consiglio di integrarlo con [javascript.info](https://javascript.info/), con una particolare attenzione per classi, Promise e async/await (e le closure, un concetto molto importante). 8 | 9 | ## Indice: 10 | 11 | * [Cos'è?](#cosè) 12 | * [Documentazione di JavaScript](#documentazione-di-javascript) 13 | * [Un linguaggio interpretato o compilato?](#un-linguaggio-interpretato-o-compilato) 14 | * [Versioni di JavaScript](#versioni-di-javascript) 15 | * [Le variabili in JavaScript](#le-variabili-in-javascript) 16 | * [I tipi](#i-tipi) 17 | * [I numeri](#i-numeri) 18 | * [Stringhe](#stringhe) 19 | * [Le classi?](#le-classi) 20 | * [Object literal](#object-literal) 21 | * [Array literal](#array-literal) 22 | * [Truthiness e falsiness](#truthiness-e--falsiness) 23 | * [Cicli for e for...of](#cicli-for-e-forof) 24 | * [Undefined](#undefined) 25 | * [Node.js REPL](#nodejs-repl) 26 | * [npm](#npm) 27 | * [node e nodemon](#node-e-nodemon) 28 | * [Importare i moduli nel codice](#importare-i-moduli-nel-codice) 29 | * [La natura asincrona di Node.js](#la-natura-asincrona-di-nodejs) 30 | * [Funzioni, funzioni anonime, e funzioni freccia](#funzioni-funzioni-anonime-e-funzioni-freccia) 31 | * [Callback, dicevamo](#callback-dicevamo) 32 | * [Il loop degli eventi](#il-loop-degli-eventi) 33 | * [Torniamo alla definizione...](#torniamo-alla-definizione) 34 | * [Express.js](#expressjs) 35 | * [Express.js: rispondere con JSON](#expressjs-rispondere-con-json) 36 | * [Express.js: middleware](#expressjs-middleware) 37 | * [Strutturare il codice in moduli](#strutturare-il-codice-in-moduli) 38 | * [Express.js: i middleware come moduli](#expressjs-i-middleware-come-moduli) 39 | * [Cose moderne: Promise](#cose-moderne-promise) 40 | * [Cose moderne: async/await](#cose-moderne-asyncawait) 41 | * [Come approfondire](#come-approfondire) 42 | 43 | ## Cos'è? 44 | 45 | **Node.js** è un runtime per JavaScript, cioè un ambiente che permette di eseguire del codice JavaScript. 46 | 47 | L'equivalente di Node.js per Java è il JRE (Java Runtime Environment), che in fase di sviluppo è affiancato dal JDK (Java Development Kit), cioè una suite di tool di compilazione per permettere lo sviluppo di un'applicazione. 48 | 49 | Per chi conosce .NET Core, vale la stessa analogia. L'SDK si usa in fase di sviluppo, mentre CoreCLR (Common Language Runtime) in fase di esecuzione del programma. 50 | 51 | ## Documentazione di JavaScript 52 | 53 | La documentazione più autorevole per trovare informazioni su JavaScript è quella di Mozilla, che si chiama MDN. Dalla [homepage di MDN](https://developer.mozilla.org/en-US/), si può accedere alla sezione dedicata a JavaScript dal menù "Technologies". 54 | 55 | [Non usare W3Schools](https://skillsandmore.org/non-usare-w3schools/), grazie. 56 | 57 | ## Un linguaggio interpretato o compilato? 58 | 59 | JavaScript non è un linguaggio compilato, ma prevalentemente interpretato. Ciò significa che per eseguire un programma scritto in JavaScript ci vuole il codice sorgente del programma. 60 | 61 | Si dice *prevalentemente* interpretato perché nelle implementazioni più recenti il codice sorgente del programma viene in realtà compilato, ma *just in time* (JIT). Significa in pratica che se hai un ciclo che esegue un'istruzione un milione di volte, l'interprete/compilatore anziché "interpretare" l'istruzione un milione di volte, la compila, in modo da aumentare le prestazioni (la compilazione JIT è leggermente più lenta dell'interpretazione, ma il tempo speso viene rapidamente e largamente recuperato). 62 | 63 | Per eseguire del codice JavaScript c'è quindi un solo passaggio, e cioè si invoca l'interprete sul codice sorgente, e lui lo esegue, subito. 64 | 65 | In Java, invece, un file di codice viene compilato in un file con estensione .class, che contiene il bytecode (cioè un linguaggio intermedio), e poi in un momento separato viene eseguito (usando la JVM). 66 | 67 | ## Versioni di JavaScript 68 | 69 | Negli ultimi anni, lo sviluppo di JavaScript ha avuto uno "sprint", anche grazie a Node.js, per cui sono spuntate in un paio di anni due versioni che hanno cambiato non di poco il modo in cui si scrive codice JavaScript. 70 | 71 | La cosa più importante da sapere è che lo standard di JavaScript rilasciato nel 2015 e chiamato **ECMAScript 2015** (o ES6 a volte) ha introdotto delle funzionalità importanti nel linguaggio, per cui quando si scrive del codice in ES2015 bisogna fare attenzione al fatto che poi l'interprete deve supportare questa versione di JavaScript. 72 | 73 | Se usi l'ultima versione LTS di Node.js non c'è da preoccuparsi, perché supporta a pieno ES2015. 74 | 75 | ## Le variabili in JavaScript 76 | 77 | C'è una cosa importante da dire sulle variabili in JavaScript. 78 | 79 | Precedentemente ad ES2015, c'era solo un modo per dichiarare ed inizializzare una variabile, e cioè usando la parola chiave `var`: 80 | 81 | ```js 82 | var gino = true; 83 | ``` 84 | 85 | Di recente è stata introdotta anche la parola chiave `let`, che ha un'importante differenza, e cioè lo scope di validità della variabile creata. 86 | 87 | ```js 88 | function ciao() { 89 | if (true) { 90 | var gatto = 1; 91 | let cane = 2; 92 | } 93 | 94 | console.log(cane); 95 | console.log(gatto); 96 | } 97 | ``` 98 | 99 | Che cosa succede qua? La variabile `gatto`, creata all'interno del blocco dell'`if`, ha in realtà scope di validità equivalente alla funzione `ciao`. Significa che la variabile `gatto` è disponibile *anche fuori dall'if*. 100 | 101 | La variabile `cane`, invece, essendo dichiarata con `let` è disponibile soltanto nel blocco in cui è stata dichiarata, e quindi nel corpo dell'`if` (che inizia e finisce con le parentesi graffe). 102 | 103 | Nel mondo reale, se non stai scrivendo codice JavaScript per il browser (che ha problemi di compatibilità), usa **sempre**, **SEMPRE** `let`. È molto più facile da comprendere (è simile a come funzionano le cose in altri linguaggi), e riduce enormemente la possibilità di fare errori o di introdurre bug difficili da trovare. Un altro vantaggio è il fatto che non si può dichiarare due volte una variabile usando `let`: 104 | 105 | ```js 106 | var gatto; 107 | var gatto; // funziona 108 | 109 | let cane; 110 | let cane; // non funziona, grazie al cane 111 | ``` 112 | 113 | ## I tipi 114 | 115 | JavaScript non è fortemente tipizzato, e i tipi non sono statici. Che vuol dire? 116 | 117 | In pratica, che il tipo di una variabile può cambiare, e che quando si accede a una variabile non c'è nessun controllo sul suo tipo. Il linguaggio ci prova (a tempo di esecuzione!), e al massimo fallisce con un'eccezione. 118 | 119 | ```js 120 | let v = 1; 121 | v = 'ciao'; // il tipo cambia 122 | v = [1, 2, 3]; // due volte 123 | v = null; // qualsiasi variabile può assumere valore null 124 | ``` 125 | 126 | Questa "feature" è sia un grande vantaggio che un grande disastro. Dà una grande libertà nel modo in cui si usano le variabili, e permette in molti casi di accorciare il codice, ma è spesso fonte di bug. Una lista di casini che seguono da questa "feature" si trova [qua](https://github.com/denysdovhan/wtfjs) (ma sono cose abbastanza avanzate, leggerle all'inizio è un po' una follia). 127 | 128 | ## I numeri 129 | 130 | Una particolarità di JavaScript è che tutti i tipi numerici sono raggruppati in un unico tipo chiamato `Number`. La rappresentazione interna (in memoria) cambia in base a se il numero è un intero, un short (8 bit), o un numero in virgola mobile, o boh, ma all'esterno è tutto un `Number`. 131 | 132 | Come si fa la conversione (parsing) di una stringa in numero? 133 | 134 | Ci sono tanti modi. La tabella che segue li riassume. L'intestazione delle colonne indica il codice eseguito, e le varie righe sono l'output dell'istruzione. 135 | 136 | ![Conversione numeri](https://i.stack.imgur.com/dzin3.png) 137 | 138 | ![](https://media.makeameme.org/created/wtf-did-i-5b5d17.jpg) 139 | 140 | Se la cosa ti spiazza, usa il metodo più semplice, che ha tra l'altro poche conseguenze indesiderate. Esempio: 141 | 142 | ```js 143 | let input = '123'; 144 | let numero = +input; 145 | ``` 146 | 147 | Detto in parole, metti un "+" davanti alla variabile contenente la stringa da convertire, e sarà convertita in numero. Se è già un numero, resta un numero. Se non è un numero, vediamo fra poco come si fa a capirlo. 148 | 149 | ## Stringhe 150 | 151 | Le stringhe *funzionano*. Supportano in automatico UTF-8, a differenza di altri linguaggi che ricordano certi simpatici rettili striscianti. 152 | 153 | Un consiglio: quasi tutti gli sviluppatori JavaScript utilizzano gli apici singoli anziché quelli doppi, a differenza di Java. 154 | 155 | Ciò significa che anche se entrambe queste forme sono corrette: 156 | 157 | ```js 158 | let a = "testo"; 159 | let b = 'testo'; 160 | ``` 161 | 162 | Quella preferita è quasi sempre la seconda. 163 | 164 | ## Le classi? 165 | 166 | In Java ci sono le classi e l'intero linguaggio è orientato agli oggetti. In JavaScript, è un casino. 167 | 168 | Prima di ES2015, le funzioni potevano essere assimilate a classi. Si poteva (e si può) scrivere: 169 | 170 | ```js 171 | function Classe() {} 172 | 173 | Classe.prototype.metodo = function() { 174 | console.log('ciao'); 175 | }; 176 | 177 | var istanza = new Classe(); 178 | ``` 179 | 180 | Questo pezzo di codice crea una funzione, modifica il *prototipo* della funzione aggiungendo un "metodo", e poi esegue `new Classe()` per creare un'istanza della classe. È tutto molto strano, fa' finta di non averlo mai visto. 181 | 182 | Nelle versioni recenti di JavaScript, il tutto è più familiare: 183 | 184 | ```js 185 | class Classe { 186 | metodo() { 187 | console.log('è colpa di mattia'); 188 | } 189 | } 190 | 191 | let istanza = new Classe(); 192 | ``` 193 | 194 | Detto questo, le classi non le troverai *quasi* mai in JavaScript o Node.js. Ci sono altri modi più consolidati di strutturare il codice, e dato che il linguaggio non ti obbliga ad avere a che fare con le classi, puoi tranquillamente continuare a credere che non esistano, un po' come fanno alcuni con le famiglie arcobaleno. 195 | 196 | Una cosa da sapere è che quando hai a che fare con le classi ci devi mettere un `new` davanti. Ad esempio, ti capiterà di scrivere `new Date();`, senza sapere se dietro quel new c'è una funzione o una classe vera e propria. Ma nulla di nuovo, no? 197 | 198 | ## Object literal 199 | 200 | Al posto delle classi, un modo mooolto diffuso per creare tipi personalizzati è utilizzare la notazione *object literal*. Questa permette di creare degli oggetti "al volo", e il risultato è simile a un dizionario, o hashmap. 201 | 202 | ```js 203 | let roba = { 204 | chiave: 'valore', 205 | fausto: false, 206 | numero: 123 207 | }; 208 | ``` 209 | 210 | A differenza delle classi, gli oggetti "anonimi" li troverai spesso, e ti troverai anche a scriverne. Ogni volta che ti serve creare un tipo "composto", usa la notazione *object literal*. È gratis. 211 | 212 | Dal codice sopra si può osservare di nuovo la flessibilità di JavaScript. Il numero di proprietà/campi, così come il loro tipo, è completamente libero, e come detto prima può cambiare durante l'esecuzione. 213 | 214 | Ad esempio, possiamo accedere a una proprietà di un oggetto e modificarla liberamente: 215 | 216 | ```js 217 | roba.numero = 'eheh'; 218 | ``` 219 | 220 | Una sintassi equivalente è questa: 221 | 222 | ```js 223 | roba['numero'] = 'eheh'; 224 | ``` 225 | 226 | Fanno la stessa identica cosa, puoi scegliere quella che ti piace di più. 227 | 228 | In JavaScript, gli oggetti sono liberamente alterabili. Ad esempio, **all'oggetto sopra si può aggiungere una proprietà, e non c'è modo di impedirlo**. 229 | 230 | ```js 231 | roba.nuovaprop = 'aaa'; 232 | ``` 233 | 234 | Questo vale anche per le classi. Anche se i campi/proprietà della classe sono ben definiti nel codice, nulla vieta di crearne di nuovi. Si può addirittura aggiungere un nuovo campo su un oggetto che non abbiamo creato noi. Ad esempio: 235 | 236 | ```js 237 | let d = new Date(); 238 | d.prop = 12; // si può fare 239 | console.log(d.prop); 240 | ``` 241 | 242 | La flessibilità della notazione object literal permette di fare cose come queste: 243 | 244 | ```js 245 | let obj = { 246 | data: { 247 | valore: 1, 248 | gino: { 249 | aaa: 'ok' 250 | } 251 | }, 252 | ok: true 253 | }; 254 | ``` 255 | 256 | E cioè l'annidamento degli oggetti è consentito senza limite di profondità. Esistono anche i riferimenti circolari, se li hai presenti. 257 | 258 | ## Array literal 259 | 260 | La notazione "literal" è disponibile anche per gli array/liste (che sono la stessa cosa!): 261 | 262 | ```js 263 | let arr = [1, 2, 3]; 264 | let arr2 = [true, 0, 'ciao']; 265 | ``` 266 | 267 | Anche in questo caso il controllo dei tipi non esiste, cioè ogni elemento dell'array può avere qualsiasi tipo, e può anche cambiare durante l'esecuzione. Per creare un array vuoto si fa così: 268 | 269 | ```js 270 | let arr = []; 271 | ``` 272 | 273 | Ci sono altri modi di farlo (come `new Array()`), ma non sono consigliati. 274 | 275 | Per aggiungere un elemento a un array: 276 | 277 | ```js 278 | arr.push(1); 279 | ``` 280 | 281 | Gli oggetti possono essere elementi di un array, ed è molto comune trovarli. Ad esempio: 282 | 283 | ```js 284 | let arr = []; 285 | arr.push({ val: 1 }); 286 | arr.push({ val: 2 }); 287 | ``` 288 | 289 | ## Truthiness e falsiness 290 | 291 | Come sai, in JavaScript esiste la *coercizione dei tipi*, quella cosa strana che permette ad esempio di confrontare una stringa con un intero, con conversione implicita. Le regole di conversione sono molto complesse, ma c'è una cosa fondamentale da sapere, e cioè **quando un valore viene valutato come truthy o falsy** ("abbastanza vero" e "abbastanza falso", diciamo). 292 | 293 | Un valore è detto falsy se è uno dei seguenti: 294 | 295 | - null 296 | - undefined 297 | - 0 298 | - '' (stringa vuota) 299 | - NaN 300 | - false 301 | 302 | Un valore è truthy se non è falsy. 303 | 304 | Sembra un casino, ma in realtà è uno strumento molto potente. In sostanza permette di fare controlli rapidi sul contenuto di una variabile, per vedere approssimativamente **se "contiene qualcosa"**. Ad esempio, supponiamo di avere una variabile `input` con un valore preso in input dall'utente, che pensiamo sia una stringa ma non sappiamo in realtà cosa abbia dentro. Possiamo scrivere: 305 | 306 | ```js 307 | // input è dichiarato da qualche parte sopra 308 | if (input) { 309 | // la variabile contiene qualcosa, 310 | // che *non è* null, undefined, 0, '', NaN, false 311 | } 312 | ``` 313 | 314 | Ancora più comune è vedere scritto: 315 | 316 | ```js 317 | if (!input) { 318 | // ritorno un errore perché l'input non è "valido" 319 | } 320 | ``` 321 | 322 | Questa strategia si può usare anche per **controllare che la conversione di qualcosa da stringa a `Number` sia avvenuta con successo**. Dalla tabella di prima si può vedere che un numero che non è un numero diventa `NaN`, cioè un valore molto speciale che indica che quella variabile non contiene un numero. Dico che è un valore molto speciale perché è difficile da trattare. Ad esempio, non è uguale nemmeno a s[é](http://www.accademiadellacrusca.it/it/lingua-italiana/consulenza-linguistica/domande-risposte/accentazione-pronome-stesso) stesso! 323 | 324 | Si può quindi verificare che un numero parsato non sia in realtà un numero così: 325 | 326 | ```js 327 | let n = +'non un numero'; 328 | 329 | if (isNaN(n)) { 330 | console.log('non è un numero'); 331 | } 332 | ``` 333 | 334 | Un modo più approssimativo è quello di usare il controllo implicito della truthiness di una variabile, quindi: 335 | 336 | ```js 337 | if (!n) { 338 | console.log('non è un numero'); 339 | } 340 | ``` 341 | 342 | Attenzione però, perché in questo caso il valore `0` non verrà considerato un numero! 343 | 344 | Un altro caso d'uso della truthiness è per fornire un valore di default/fallback per una variabile. Esempio: 345 | 346 | ```js 347 | const PORT = process.env.PORT || 3000; 348 | ``` 349 | 350 | Il significato è che la costante `PORT` assume il valore della variabile `process.env.PORT` (cioè una variabile d'ambiente di nome `PORT`) se ha un valore (secondo la regola sopra), altrimenti il valore costante 3000. 351 | 352 | ## Cicli for e for...of 353 | 354 | Il ciclo for esiste e funziona come negli altri linguaggi: 355 | 356 | ```js 357 | for (let i = 0; i <= 10; i++) { 358 | // boh 359 | } 360 | ``` 361 | 362 | Il foreach non esiste, ma è sostituito da `for...of`, praticamente uguale: 363 | 364 | ```js 365 | let arr = [1, 2, 3]; 366 | 367 | for (let item of arr) { 368 | console.log(item); 369 | } 370 | ``` 371 | 372 | Esiste anche un altro modo per iterare un array, usando la funzione `forEach` definita sul tipo `Array`: 373 | 374 | ```js 375 | arr.forEach((item) => { 376 | console.log(item); 377 | }); 378 | ``` 379 | 380 | ## Undefined 381 | 382 | In JavaScript, **le variabili che non sono ancora state inizializzate si possono usare**. Mentre in Java e in molti altri linguaggi una variabile non inizializzata non è "leggibile" finché non assume un valore, in JavaScript ha sempre un valore, che inizialmente è `undefined`. 383 | 384 | Si può controllare se una variabile è `undefined` così: 385 | 386 | ```js 387 | let a; // dichiarata ma senza valore 388 | console.log(a == undefined); // questo scrive true 389 | ``` 390 | 391 | **Se la variabile non è dichiarata, questo metodo non funziona**. Bisogna invece utilizzare l'operatore `typeof`, così: 392 | 393 | ```js 394 | // non ho ancora dichiarato nesuna variabile 395 | console.log(typeof a == 'undefined'); // true 396 | ``` 397 | 398 | ## Node.js REPL 399 | 400 | Siamo a metà. È ora di passare a Node.js. 401 | 402 | Una delle prime cose da sapere quando si prende in mano Node.js è che **JavaScript è un linguaggio di scripting**. Significa che il codice può essere scritto ed eseguito inserendolo direttamente in un file .js, senza dover inserire funzioni "main", oppure classi, ecc. Il codice viene eseguito come script (come avviene con l'amico bash). 403 | 404 | C'è di più, aprendo una finestra del terminale e scrivendo `node`, si entra nella [REPL](https://en.wikipedia.org/wiki/Read–eval–print_loop) di Node.js, e cioè una modalità interattiva in cui si può scrivere del codice JavaScript riga per riga, e le istruzioni vengono eseguite "istantaneamente". 405 | 406 | ## npm 407 | 408 | npm è il gestore dei pacchetti di Node.js, installato in automatico con Node.js. I pacchetti disponibili sono consultabili sul sito web [npmjs.com](https://www.npmjs.com/). 409 | 410 | Nelle versioni recenti di npm, per installare un nuovo modulo nel progetto corrente si usa: 411 | 412 | ```bash 413 | npm install nomemodulo 414 | ``` 415 | 416 | È **importante** aver eseguito `npm init` **prima** di questo comando, perché altrimenti l'installazione del modulo potrebbe non essere eseguita nella cartella corrente ma in una "padre". 417 | 418 | I comandi `npm init` e poi `npm install` creano due file: *package.json* e *package.lock.json*. 419 | 420 | - *package.json* memorizza le informazioni sul progetto, tra cui la lista delle sue dipendenze 421 | - *package.lock.json* memorizza le versioni *esatte* delle dipendenze del progetto, in modo che se un'altra persona vuole poi continuare lo sviluppo sul progetto, può scaricare le stesse *identiche* dipendenze 422 | 423 | I moduli scaricati (cioè le dipendenze) vengono installati nella cartella `node_modules`, che con il tempo diventerà enorme. Contiene il codice sorgente di tutti i moduli di cui il programma ha bisogno per funzionare. 424 | 425 | Come si utilizza **npm assieme a git**? 426 | 427 | - `npm init` va eseguito soltanto la prima volta, per creare il **file package.json, che va committato** 428 | - `npm install modulo` si usa ogni volta che si deve aggiungere un nuovo modulo. Il comando aggiorna sia il file *package.json* che il file *package.lock.json*. **Entrambi i file vanno committati** nella repository 429 | - la cartella `node_modules` **non va mai committata** 430 | - quando si scarica un progetto da git, bisogna installare le sue dipendenze. Per farlo, si esegue `npm install` senza nessuna opzione, così le dipendenze vengono lette in automatico dai file *package.json* e *package.lock.json* 431 | 432 | Consiglio anche di usare il sito web [gitignore.io](https://www.gitignore.io/) per generare un file .gitignore per Node.js e il vostro sistema operativo, da inserire nella radice della repository. L'effetto sarà quello di impedire che file che *devono* restare locali vengano tracciati da git. 433 | 434 | ## node e nodemon 435 | 436 | Per eseguire un file JavaScript con Node.js, scrivi in un terminale: 437 | 438 | ```sh 439 | node index.js 440 | ``` 441 | 442 | Dove `index.js` è l'*entrypoint* del programma. 443 | 444 | Quando i file sorgente vengono modificati, per riavviare l'applicazione bisogna interrompere con CTRL+C, e poi eseguire di nuovo il comando. 445 | 446 | Più facilmente, si può installare il modulo `nodemon` globalmente (cioè in una cartella di sistema che vale per tutti i progetti), e poi usarlo al posto di node. In questo modo, il processo si riavvierà in automatico ad ogni modifica del codice sorgente. 447 | 448 | Da eseguire solo una volta: 449 | 450 | ```sh 451 | npm install -g nodemon 452 | ``` 453 | 454 | Per avviare un programma con `nodemon`: 455 | 456 | ```sh 457 | nodemon index.js 458 | ``` 459 | 460 | ## Importare i moduli nel codice 461 | 462 | Dopo aver installato un modulo (ad es. `express` oppure `request`), il modulo può essere importato nel programma scrivendo: 463 | 464 | ```js 465 | const express = require('express'); 466 | ``` 467 | 468 | Due cose da notare: 469 | 470 | - la funzione `require` è fornita da Node.js, e serve appunto per importare un modulo 471 | - in genere si dichiara il modulo come costante (con `const`), in modo che non possa essere riassegnato successivamente nel codice 472 | 473 | Il modulo importato corrisponde di solito a una funzione o a un un oggetto, e permette quindi di fare cose del tipo: 474 | 475 | ```js 476 | const modulo = require('modulo'); 477 | modulo(); // richiamo il modulo come funzione 478 | modulo.getQualcosa(); // il modulo è un oggetto, espone delle funzioni 479 | ``` 480 | 481 | Per sapere come si usa un modulo, bisogna fare riferimento alla documentazione del modulo, oppure al suo codice sorgente. 482 | 483 | ## La natura asincrona di Node.js 484 | 485 | Sei concentrato? [Massima concentrazione](https://www.repstatic.it/content/nazionale/img/2018/05/16/142407308-f47a41b2-2e53-4233-bec5-6a3c29935ab5.jpg). Questa parte è importantissima. 486 | 487 | **Node.js esegue il codice utente sempre e comunque in un unico thread**. Non significa che il runtime utilizza un thread per fare tutte le sue cose, ma ne fornisce soltanto uno allo sviluppatore, e non è nemmeno possibile crearne altri manualmente. 488 | 489 | Questo metodo funziona perché **le operazioni di I/O (input/output) vengono eseguite in modo asincrono rispetto al thread del programma**. 490 | 491 | Ogni volta che il programma richiede la lettura o la scrittura di un file, oppure di scrivere su un socket di rete (quindi ad esempio per inviare una richiesta HTTP), **Node.js trasferisce la richiesta al file system o ai livelli di rete inferiori, e poi libera il thread**. 492 | 493 | **In Java**, invece, quando si legge un file o si scrive su uno stream le chiamate sono *bloccanti*. Significa che mentre il programma è in attesa di una risposta dal file system, **il thread è bloccato**, e cioè sta lì letteralmente a fare niente e nessun altro codice può essere eseguito su quel thread. 494 | 495 | Nella pratica l'asincronismo di JavaScript/Node.js si traduce nel seguente codice: 496 | 497 | ```js 498 | const request = require('request'); 499 | 500 | let url = 'https://unitn.it'; 501 | 502 | request(url, function finished(err, res, body) { 503 | console.log(res.statusCode); 504 | }); 505 | ``` 506 | 507 | Cosa sta succedendo, in breve? 508 | 509 | - importo il modulo `request`, che ho scaricato da npm (serve per inviare richieste HTTP/S). Il modulo è una funzione, e cioè posso "metterlo in moto" scrivendo `request()` 510 | - chiamo `request()`, e passo come primo parametro l'URL del sito web da cui voglio scaricare i dati, e **come secondo parametro una funzione** 511 | - la chiamata della funzione `request` esegue del codice sull'unico thread di Node.js, e poi **passa la richiesta di rete al sistema operativo** 512 | - quando la richiesta di rete termina, il modulo `request` si occupa di chiamare la **funzione di callback** che abbiamo passato come parametro, in modo che il risultato possa essere elaborato 513 | 514 | Ora apriamo una parentesi, e vediamo come si scrivono e si usano le funzioni. Poi torniamo a capire meglio il funzionamento asincrono di JavaScript. **Sempre massima concentrazione**. 515 | 516 | ## Funzioni, funzioni anonime, e funzioni freccia 517 | 518 | La sintassi per creare una funzione con un nome è molto semplice: 519 | 520 | ```js 521 | function nomeFunzione(x, y) { 522 | // corpo 523 | } 524 | ``` 525 | 526 | Un po' di cose da notare: 527 | 528 | - il tipo di ritorno non va specificato 529 | - il nome della funzione utilizza per convenzione il *camelCase* 530 | - i parametri della funzione non hanno tipo ma soltanto nome 531 | 532 | Una funzione può anche essere anonima, e quindi non avere un nome. Ad esempio: 533 | 534 | ```js 535 | function(x, y) { /* codice */ } 536 | ``` 537 | 538 | A questo punto però la funzione è dispersa nel nulla, per cui possiamo assegnarla a una variabile per poi poterla chiamare: 539 | 540 | ```js 541 | let fn = function(x, y) { /* codice */ }; 542 | ``` 543 | 544 | A partire da ES2015, è disponibile una sintassi ancora più breve per creare una funzione anonima, che prende il nome di "**funzione a freccia**", o "arrow function": 545 | 546 | ```js 547 | let fn = (x, y) => { /* codice */ }; 548 | ``` 549 | 550 | ...che normalmente viene scritta su più righe: 551 | 552 | ```js 553 | let fn = (x, y) => { 554 | // codice 555 | }; 556 | ``` 557 | 558 | La funzione `fn` si può *in ogni caso* chiamare come una qualsiasi funzione scrivendo ad esempio `fn(1, 2)`. 559 | 560 | Riprendiamo il codice di prima. Vediamo che c'è una funzione con un nome (`finished`), passata come parametro. 561 | 562 | ```js 563 | request(url, function finished(err, res, body) { 564 | console.log(res.statusCode); 565 | }); 566 | ``` 567 | 568 | Riscriviamo ora la funzione utilizzando la sintassi a freccia: 569 | 570 | ```js 571 | request(url, (err, res, body) => { 572 | console.log(res.statusCode); 573 | }); 574 | ``` 575 | 576 | Ecco, questa è attualmente la sintassi consigliata per le *funzioni callback* (ci arriviamo in un attimo). Quindi, quando devi passare una funzione come parametro, usa una funzione a freccia, perché così fan tutti (semicit.). 577 | 578 | ## Callback, dicevamo 579 | 580 | Una **funzione di callback** è una funzione che viene chiamata al termine dell'elaborazione di una richiesta di I/O asincrona. 581 | 582 | Nell'esempio sopra, quando il modulo `request` ha ricevuto dal sistema operativo la "notifica" che l'operazione di rete è terminata, la funzione di callback che è stata passata da noi sviluppatori come parametro viene chiamata e quindi eseguita. 583 | 584 | Prima o poi ti capiterà di utilizzare le callback nel tuo codice. Ad esempio, se volessi spostare il codice che fa la richiesta HTTP, che abbiamo visto sopra, in una funzione dedicata, dovrai fare qualcosa del tipo: 585 | 586 | ```js 587 | function getResponseStatusCode(url, callback) { 588 | request(url, (err, res, body) => { 589 | callback(res.statusCode); 590 | }); 591 | } 592 | 593 | let url = 'https://unitn.it'; 594 | 595 | getResponseStatusCode(url, (code) => { 596 | console.log('Response status code was: ' + code); 597 | }); 598 | ``` 599 | 600 | Phew. Ci sono delle cose da chiarire qua. La funzione `getResponseStatusCode` prende come input un URL (una stringa) e una funzione di callback. All'interno della funzione, `request` viene invocato, e quando termina la funzione di callback (chiamata `callback`) viene chiamata, passando come parametro il codice di risposta HTTP. 601 | 602 | Il codice di risposta lo ritroviamo poi nella penultima riga del codice, quando all'interno di un'altra callback viene letto usando il parametro. 603 | 604 | Una pratica diffusa per le funzioni di callback si chiama **error-first callback**, e consiste nel passare come **primo parametro un errore** (di tipo `Error`, che è in pratica l'equivalente di un'eccezione), e come **secondo parametro il risultato dell'operazione**. Il codice di prima con la gestione degli errori diventerebbe quindi: 605 | 606 | ```js 607 | function getResponseStatusCode(url, callback) { 608 | request(url, (err, res, body) => { 609 | if (err) { // controlla eventuali errori di rete come i timeout 610 | callback(err); 611 | return; 612 | } 613 | 614 | callback(null, res.statusCode); 615 | }); 616 | } 617 | 618 | let url = 'https://unitn.it'; 619 | 620 | getResponseStatusCode(url, (err, code) => { 621 | if (err) { 622 | console.log('An error has occured'); 623 | console.log(err); 624 | return; 625 | } 626 | 627 | console.log('Response status code was: ' + code); 628 | }); 629 | ``` 630 | 631 | **Le funzioni asincrone adottano questa convenzione quasi sempre**, per cui ti capiterà di scrivere callback nel formato `(err, result) => {}` molto frequentemente. Ad esempio, tutte le funzioni asincrone fornite da Node.js, tra cui quelle per leggere e scrivere file, adottano questa convenzione. Soltanto alcuni (rari) moduli hanno deciso di recente di rimuovere il supporto alle callback e di passare alle Promise, che sono spiegate più avanti. 632 | 633 | Il funzionamento asincrono con le callback di Node.js impedisce di scrivere codice sequenziale come negli altri linguaggi. Se vogliamo quindi eseguire una richiesta asincrona dopo l'altra, dobbiamo *annidare* le richieste all'interno delle callback. In modo semplificato, intendo questo: 634 | 635 | ```js 636 | one(() => { 637 | console.log('Uno'); 638 | 639 | two(() => { 640 | console.log('Due'); 641 | 642 | three(() => { 643 | console.log('Tre'); 644 | }); 645 | }); 646 | }); 647 | 648 | console.log('Zero'); 649 | ``` 650 | 651 | Se supponiamo che le funzioni `one`, `two,` e `three` siano asincrone, le istruzioni `console.log()` indicano l'ordine dell'output. 652 | 653 | Se invece avessimo scritto il codice seguente, l'ordine dell'output sarebbe stato imprevedibile. 654 | 655 | ```js 656 | one(() => { 657 | console.log('Uno'); 658 | }); 659 | 660 | two(() => { 661 | console.log('Due'); 662 | }); 663 | ``` 664 | 665 | ## Il loop degli eventi 666 | 667 | Abbiamo detto che Node.js ha un solo thread per eseguire il codice. Ma come funziona nello specifico? Chi decide quale codice viene eseguito? 668 | 669 | Tutto si basa sul loop degli eventi (*event loop*, come dicono quelli). È in sostanza un ciclo che esegue porzioni di codice sincrono, di continuo, una dopo l'altra, finché c'è qualcosa da processare. 670 | 671 | Per capire meglio, rubo uno schema da [qua](https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c): 672 | 673 | ![Event loop](https://cdn-images-1.medium.com/max/1600/1*ROxiavz7LeRpIfcgRDE7CA.png) 674 | 675 | Sull'asse delle ascisse troviamo il tempo, e i blocchi verdi sono le varie fasi che compongono ogni singolo "loop". Come vedi, tra le tante c'è una fase che esegue i timer, e **una che esegue le callback**, cioè in pratica tutto il codice utente che scriverai. Ogni fase ha una coda FIFO contenente funzioni che devono essere eseguite. 676 | 677 | Se volessimo, Node.js ci permetterebbe anche di bypassare queste code, ad esempio utilizzando `setImmediate(fn)`, che esegue la funzione specificata al prossimo loop, indipendentemente da quanto altro codice abbiamo in coda. 678 | 679 | Si può anche utilizzare la funzione `process.nextTick(fn)`, che permette di schedulare l'esecuzione della funzione al prossimo tick (si veda il diagramma per capire cos'è un tick). 680 | 681 | Per dimostrare il fatto che Node.js esegue una funzione alla volta, prendiamo il seguente codice: 682 | 683 | ```js 684 | setTimeout(() => { 685 | console.log('Timeout expired'); 686 | }, 1000); 687 | 688 | while (true) { 689 | ; 690 | } 691 | ``` 692 | 693 | La chiamata a `setTimeout` aggiunge nella coda dei timeout una funzione da eseguire fra un secondo. Poi c'è un ciclo infinito, che non fa niente ma tiene la CPU occupata. 694 | 695 | Eseguendo questo codice, si scoprirà che **il codice all'interno del timeout non verrà *mai* eseguito**, perché il loop degli eventi è impegnato ad eseguire il ciclo infinito. 696 | 697 | **Questo è il motivo fondamentale per cui Node.js non va usato per eseguire operazioni che richiedono molta CPU**. Immaginate un server web che gestisce 10 richieste al secondo. Se ciascuna di queste richieste impiega un secondo di CPU (quindi ad esempio c'è un ciclo enorme), le richieste devono attendere rispettivamente 1, 2, 3, ecc. secondi prima di ricevere una risposta! 698 | 699 | **RICORDA**: mai inserire codice sincrono che richiede molto tempo ad essere eseguito, altrimenti Node.js non worka! La "potenza" di Node.js è quella di riuscire a ottenere prestazioni eccezionali quando ci sono tante operazioni di I/O (ad esempio lettura/scrittura su un database), ma con poco codice che usa la CPU! 700 | 701 | C'è un'altra cosa da notare. Scriviamo del codice che esegue delle operazioni sincrone, poi chiama qualcosa di asincrono, e poi nient'altro. Nel momento in cui c'è la chiamata asincrona, il loop degli eventi "stacca" la CPU dalla funzione, e continua eventualmente il suo lavoro con altro codice in coda. 702 | 703 | Ci sei ancora? Vediamo un esempio, con dei commenti: 704 | 705 | ```js 706 | let out = ''; 707 | while (i < 100) { 708 | out += i + ';'; 709 | } 710 | // ^^^^ le tre righe sopra sono CODICE SINCRONO 711 | // vengono eseguite tutte insieme E NON POSSONO ESSERE MAI MAI MAI INTERROTTE 712 | 713 | // la riga sotto effettua internamente una chiamata ASINCRONA al sistema operativo 714 | // soltanto quando la richiesta di rete sarà terminata, il controllo sarà passato alla funzione di callback 715 | // cioè: la richiesta *non è bloccante* 716 | request('https://unitn.it', () => { 717 | console.log('Questo viene eseguito dopo'); 718 | }); 719 | ``` 720 | 721 | Essendo Node.js *single threaded*, bisogna raramente preoccuparsi dei problemi di sincronizzazione, proprio perché **un blocco di codice sincrono non può mai essere interrotto a metà**, se non per la presenza di una richiesta di I/O. 722 | 723 | ## Torniamo alla definizione... 724 | 725 | Spesso si dice che Node.js è un runtime con I/O *non-blocking* e *event-driven*. 726 | 727 | Ora puoi capire meglio perché: 728 | 729 | - *non-blocking*, perché quando ci sono operazioni di I/O il thread non sta lì ad aspettare bloccato 730 | - *event-driven* perché c'è il loop degli eventi 731 | 732 | ## Express.js 733 | 734 | Express.js è un framework per realizzare applicazioni web in Node.js, utilizzando il protocollo HTTP. Non è considerato da tutti il migliore, ma è sicuramente il più popolare. 735 | 736 | Come si scrive un semplice server web in Express.js? Così: 737 | 738 | ```js 739 | const express = require('express'); 740 | const app = express(); 741 | 742 | app.get('/', (req, res) => { 743 | res.send('Hello'); 744 | }); 745 | 746 | app.listen(3000); 747 | ``` 748 | 749 | **Stiamo mettendo in pratica tutto quanto detto finora.** 750 | 751 | Il modulo `express` viene importato come costante, e questo modulo è una funzione. Nella seconda riga infatti eseguiamo `express()` per creare un'istanza del server web. Come si fa a sapere che si fa così e magari non scrivendo `new express()`? Dipende da modulo a modulo, quindi bisogna leggere la sua documentazione. 752 | 753 | Successivamente, nel codice registriamo una funzione per ricevere le richieste GET all'endpoint `/` del server web. La funzione è una funzione di callback, e in questo caso riceve due variabili come argomenti: quella che descrive la richiesta e quella che descrive la risposta. `res` permette anche di rispondere e inviare qualcosa al client. 754 | 755 | Alla fine del codice il server viene avviato con una chiamata a `app.listen()`. Da quel momento in poi, il server accetta richieste HTTP ed utilizza i middleware e le route specificate in precedenza per gestire le richieste. 756 | 757 | ## Express.js: rispondere con JSON 758 | 759 | Il codice sopra si può modificare lievemente per fare in modo che risponda alle richieste con un oggetto, che viene serializzato (cioè convertito da oggetto a stringa) in automatico da Express. 760 | 761 | ```js 762 | app.get('/', (req, res) => { 763 | let roba = { name: 'Niccolò' }; 764 | 765 | res.send(roba); 766 | }); 767 | ``` 768 | 769 | Con questo codice però c'è un problema. Se non diciamo a Express di fare diversamente, lui/lei assume che quello che vogliamo inviare sia una pagina HTML. Imposterà quindi l'header HTTP `Content-Type` scrivendoci dentro `text/html`. 770 | 771 | Per "risolvere" questo problema, dobbiamo sostituire la riga `res.send(roba);` con: 772 | 773 | ```js 774 | res.json(roba); 775 | ``` 776 | 777 | Fa la stessa cosa di prima, ma imposta l'header `Content-Type: application/json` in automatico. 778 | 779 | ## Express.js: middleware 780 | 781 | Se vieni da Java Servlet, conoscerai i filtri, cioè catene di metodi che permettono di manipolare la richiesta/risposta HTTP. 782 | 783 | Si può fare anche usando Express.js, con i **middleware**. 784 | 785 | ```js 786 | app.use((req, res, next) => { 787 | console.log('Sta arrivando una qualsiasi richiesta'); 788 | next(); 789 | }); 790 | 791 | app.use('/', (req, res, next) => { 792 | console.log('Sta arrivando una richiesta a /'); 793 | next(); 794 | }); 795 | 796 | app.get('/', (req, res) => { 797 | let roba = { name: 'Niccolò' }; 798 | 799 | res.send(roba); 800 | }); 801 | 802 | app.use((req, res) => { 803 | res.status(404).json({ error: 'Page not found' }); 804 | }); 805 | ``` 806 | 807 | Nel codice sopra, registriamo un middleware chiamando `app.use()`. La funzione di callback viene chiamata non appena arriva una richiesta HTTP (una qualsiasi), e **l'elaborazione non procede finché non viene chiamata la funzione `next()`**. 808 | 809 | La stessa cosa avviene con il secondo middleware registrato, che questa volta però è specifico per l'endpoint `/` del server web. 810 | 811 | I middleware sono spesso comodi perché **permettono di manipolare la richiesta** in molti modi, ad esempio facendo il **parsing del corpo della richiesta prima dell'elaborazione dei suoi dati**. Possiamo usare i middleware anche per **gestire l'autenticazione/autorizzazione**, fermando subito le richieste non valide. 812 | 813 | Un'altra applicazione interessante è quella di **mostrare una pagina di errore 404 personalizzata**. Lo si può fare come nell'esempio sopra, aggiungendo un middleware dopo tutti gli altri. Quel middleware sarà raggiunto soltanto se nessun middleware precedente avrà preso in carico la richiesta HTTP. 814 | 815 | ## Strutturare il codice in moduli 816 | 817 | Abbiamo detto che le classi in JavaScript si usano poco. Ma allora come si struttura il codice? 818 | 819 | Si possono usare i moduli. Semplificando, **in Node.js ogni file che scriviamo è un modulo**. Ogni file può quindi decidere di *esportare* delle funzioni, che saranno accessibili dagli altri moduli. 820 | 821 | Facciamo un esempio. Questo è il file `modulo.js`, e l'ultima riga esporta una funzione: 822 | 823 | ```js 824 | function getName() { 825 | return "Niccolò"; 826 | } 827 | 828 | module.exports = getName; 829 | ``` 830 | 831 | Negli altri file possiamo poi scrivere: 832 | 833 | ```js 834 | const modulo = require('./modulo.js'); 835 | let name = modulo(); 836 | 837 | console.log(name); 838 | ``` 839 | 840 | Il modulo è *diventato* una funzione, ma con il vantaggio che all'interno del modulo ci possono essere altri cento metodi, inaccessibili dall'esterno! 841 | 842 | Un modulo può anche esportare più di una funzione, ad esempio (`modulo.js`): 843 | 844 | ```js 845 | function getName() { 846 | return "Niccolò"; 847 | } 848 | 849 | function getAge() { 850 | return 21; 851 | } 852 | 853 | module.exports = { getName, getAge }; 854 | ``` 855 | 856 | Nota: l'ultima riga è equivalente a scrivere: 857 | 858 | ```js 859 | module.exports = { 860 | getName: getName, 861 | getAge: getAge 862 | }; 863 | ``` 864 | 865 | Negli altri file si potrà poi usare il modulo così: 866 | 867 | ```js 868 | const modulo = require('./modulo.js'); 869 | let name = modulo.getName(); 870 | let age = modulo.getAge(); 871 | 872 | console.log(name + '(' + age + ')'); 873 | ``` 874 | 875 | Non è obbligatorio esportare tutte le funzioni contenute in un modulo, anzi: il modulo deve fornire un'interfaccia pubblica per gli altri moduli, ma tenere "privato" tutto ciò che non deve essere accessibile direttamente. 876 | 877 | ## Express.js: i middleware come moduli 878 | 879 | I moduli si possono sfruttare anche in combinazione con Express.js. Immaginiamo di avere una API scritta con Express, con due endpoint `/movies` e `/songs`. Il codice assomiglierà più o meno a: 880 | 881 | ```js 882 | const express = require('express'); 883 | const app = express(); 884 | 885 | app.get('/movies', (req, res) => { 886 | let movies = [ 887 | { title: 'Sunshine', year: 2007 }, 888 | { title: 'Your Name.', year: 2016 } 889 | ]; 890 | 891 | res.json(movies); 892 | }); 893 | 894 | app.get('/songs', (req, res) => { 895 | let songs = [ 896 | { title: 'Ophelia', artist: 'Roo Panes' }, 897 | { title: 'Gosh', artist: 'Jamie xx' } 898 | ]; 899 | 900 | res.json(songs); 901 | }); 902 | 903 | app.listen(3000); 904 | ``` 905 | 906 | Quando gli endpoint diventano tanti e più complessi, il codice può diventare ingestibile. Si può allora spostare il codice delle funzioni callback in moduli separati. Ad esempio: 907 | 908 | File `movies.js`: 909 | 910 | ```js 911 | let getMovies = (req, res) => { 912 | let movies = [ 913 | { title: 'Sunshine', year: 2007 }, 914 | { title: 'Your Name.', year: 2016 } 915 | ]; 916 | 917 | res.json(movies); 918 | }; 919 | 920 | module.exports = { getMovies }; 921 | ``` 922 | 923 | File `songs.js`: 924 | 925 | ```js 926 | let getSongs = (req, res) => { 927 | let songs = [ 928 | { title: 'Ophelia', artist: 'Roo Panes' }, 929 | { title: 'Gosh', artist: 'Jamie xx' } 930 | ]; 931 | 932 | res.json(songs); 933 | }; 934 | 935 | module.exports = { getSongs }; 936 | ``` 937 | 938 | Il file principale diventa quindi molto più compatto: 939 | 940 | ```js 941 | const express = require('express'); 942 | const app = express(); 943 | 944 | const movies = require('./movies.js'); 945 | const songs = require('./songs.js'); 946 | 947 | app.get('/movies', movies.getMovies); 948 | app.get('/songs', songs.getSongs); 949 | 950 | app.listen(3000); 951 | ``` 952 | 953 | ## Cose moderne: Promise 954 | 955 | Come detto prima, quando si hanno più operazioni asincrone da eseguire in sequenza il codice va "annidato" all'interno delle callback. 956 | 957 | Questa pratica genera però in alcuni casi un problema che viene chiamato **callback hell**. Avviene quando ci sono molte callback dentro altre callback, e quindi l'indentazione del codice tende a crescere molto rapidamente, con problemi di leggibilità del codice e maggiore probabilità di introdurre bug. 958 | 959 | Un esempio potrebbe essere questo: 960 | 961 | ```js 962 | downloadFile((path) => { 963 | openFile(path, (fd) => { 964 | readFile(fd, (content) => { 965 | parseFile(content, (data) => { 966 | process(data, () => { 967 | console.log('Finish'); 968 | }); 969 | }); 970 | }); 971 | }); 972 | }); 973 | ``` 974 | 975 | Le funzioni sono inventate, ma l'idea di base è che quando ci sono molte operazioni asincrone che hanno bisogno del risultato di un'altra operazione asincrona, si può arrivare a una situazione di questo tipo. 976 | 977 | Le **Promise** sono un tentativo di risolvere questo problema. L'obiettivo è "appiattire" la struttura del codice, ed evitare quindi l'indentazione ad ogni chiamata asincrona. 978 | 979 | Supponiamo per un attimo di avere una funzione che ritorni una Promise. Se con le callback dovevamo chiamare una funzione e passare una funzione di callback come parametro, con le Promise la callback non va passata alla funzione direttamente, ma a una funzione `.then()`, da eseguire sulla Promise. 980 | 981 | Vediamo un esempio che è meglio: 982 | 983 | ```js 984 | downloadFile().then((path) => { 985 | // questa è la callback 986 | }); 987 | ``` 988 | 989 | La funzione `downloadFile` ritorna una Promise. Dobbiamo saperlo in anticipo, perché se chi ha scritto quella funzione non ha pensato alle Promise, questa cosa non funziona. 990 | 991 | La Promise ritornata dalla funzione è un oggetto, su cui sono definiti dei metodi. Uno di questi è la funzione `then(fn)`. È facile intuire a cosa serve. Quando l'esecuzione del codice della Promise termina (si dice che la Promise viene *risolta*), la funzione di callback che specifichiamo viene chiamata. 992 | 993 | **Una Promise non è altro che un "contenitore" di codice. Quando una Promise viene creata, il suo codice viene eseguito istantaneamente!** 994 | 995 | Quanto detto finora non risolve però il problema del "callback hell". Infatti, se riscriviamo il codice di prima con le Promise, siamo da capo, abbiamo solo spostato il problema: 996 | 997 | ```js 998 | downloadFile().then((path) => { 999 | openFile(path).then((fd) => { 1000 | readFile(fd).then((content) => { 1001 | parseFile(content).then((data) => { 1002 | process(data).then(() => { 1003 | console.log('Finish'); 1004 | }); 1005 | }); 1006 | }); 1007 | }); 1008 | }); 1009 | ``` 1010 | 1011 | La funzionalità cruciale delle Promise che ci permette di risolvere il callback hell è la *concatenabilità* delle Promise. Significa che una Promise può essere "collegata" a un'altra Promise. 1012 | 1013 | Vediamo subito l'esempio sopra con le Promise usate bene: 1014 | 1015 | ```js 1016 | downloadFile() 1017 | .then((path) => { 1018 | return openFile(path); 1019 | }) 1020 | .then((fd) => { 1021 | return readFile(fd); 1022 | }) 1023 | .then((content) => { 1024 | return parseFile(content); 1025 | }) 1026 | .then((data) => { 1027 | return process(data); 1028 | }) 1029 | .then(() => { 1030 | console.log('Finish'); 1031 | }); 1032 | ``` 1033 | 1034 | Visto? Abbiamo scritto una catena di Promise. **Stiamo ancora usando le callback**, ma non stiamo più aumentando l'indentazione ad ogni chiamata asincrona. 1035 | 1036 | Come si gestiscono gli errori? Con le Promise non abbiamo più l'*error-first callback* che abbiamo visto prima. Gli errori possono essere gestisti con la funzione `catch(fn)`. Il codice sopra diventa quindi una cosa del genere: 1037 | 1038 | ```js 1039 | downloadFile() 1040 | .then((path) => { 1041 | return openFile(path); 1042 | }) 1043 | .then((fd) => { 1044 | return readFile(fd); 1045 | }) 1046 | .then((content) => { 1047 | return parseFile(content); 1048 | }) 1049 | .then((data) => { 1050 | return process(data); 1051 | }) 1052 | .then(() => { 1053 | console.log('Finish'); 1054 | }) 1055 | .catch((err) => { 1056 | console.log('There\'s been an error'); 1057 | console.log(err); 1058 | }); 1059 | ``` 1060 | 1061 | **Il gestore degli errori (quello in fondo) vale per tutte le Promise della catena**. Se un'operazione fallisce, la catena si interrompe e il prossimo gestore degli errori viene richiamato. 1062 | 1063 | Ti starai chiedendo: ma tutti gli esempi che abbiamo visto finora usavano le callback normali, come si fa a usare le Promise? 1064 | 1065 | Beh... È un casino. **Se vuoi usare le Promise, l'ideale sarebbe che i moduli che usi supportino le Promise**. Ad esempio, il modulo `node-fetch` per eseguire richieste HTTP le supporta in automatico. Puoi quindi scrivere: 1066 | 1067 | ```js 1068 | const fetch = require('node-fetch'); 1069 | 1070 | fetch('https://unitn.it') 1071 | .then((resp) => { 1072 | console.log(resp.text()); 1073 | }); 1074 | ``` 1075 | 1076 | Ma c'è un piiiiccolo problema. **I moduli nativi di Node.js**, ad esempio quello per leggere i file dal file system, **non supportano le Promise**. 1077 | 1078 | A partire da Node.js 8, esiste però una funzione apposita per "convertire" le *error-first callback* in Promise. Si fa così: 1079 | 1080 | ```js 1081 | const util = require('util'); 1082 | const fs = require('fs'); 1083 | 1084 | const readFile = promisify(fs.readFile); 1085 | 1086 | // ora readFile è una Promise 1087 | readFile('file.txt').then((content) => { 1088 | console.log(content); 1089 | }); 1090 | ``` 1091 | 1092 | Cosa succede all'interno di `promisify`? Viene creata in modo automatico una Promise. Se vuoi capire meglio, dai un'occhiata al [codice sorgente di Node.js](https://github.com/nodejs/node/blob/v11.x/lib/internal/util.js#L255). È JavaScript abbastanza avanzato, ma a un certo punto (L275) si vede che viene creata la Promise, con `new Promise`. Poi viene chiamata la funzione da "promisificare" (L276), e la Promise viene "risolta" o "respinta" in base a se ci sono o meno errori. 1093 | 1094 | **SE TI SENTI PERSO**: lo sono anche io. Non sei obbligato/a ad usare le Promise, la stragrande maggioranza dei moduli non le supporta ancora, e il problema del callback hell non è così comune se si organizza bene il codice. Ma se la cosa ti appassiona, la prossima sezione è per te. 1095 | 1096 | **Bonus**: `Promise.all([p1, p2, ..., pn])` serve per creare una Promise che al suo interno esegue il codice di tutte le Promise `p1`, `p2`, ecc., in modo concorrente. I risultati vengono poi ritornati tutti insieme. C'è un esempio sulla [pagina di MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all). 1097 | 1098 | ## Cose moderne: async/await 1099 | 1100 | Ora che abbiamo incasinato le cose per bene con le Promise, proviamo a semplificarle. A partire da Node.js 7.6 (versione di JavaScript ES2017), è stato abilitato il supporto all'operatore `await`. Il suo scopo è quello di prendere una Promise e di eseguirla *come se fosse codice sincrono*. 1101 | 1102 | Ad esempio, prendiamo la Promise per leggere un file che abbiamo creato prima, e usiamola con `await`: 1103 | 1104 | ```js 1105 | let content = await readFile('file.txt'); 1106 | console.log(content); 1107 | ``` 1108 | 1109 | **È ancora tutto asincrono e non bloccante, ma l'impressione è che il codice sia sincrono (e sequenziale).** 1110 | 1111 | Con `await`, le callback non si usano più. Ma per poterlo usare, devi avere a disposizione delle Promise. 1112 | 1113 | Per far funzionare il pezzo di codice sopra, dobbiamo inserirlo in una funzione, e dichiarare la funzione come asincrona. Esempio: 1114 | 1115 | ```js 1116 | async function run() { 1117 | let content = await readFile('file.txt'); 1118 | return content; 1119 | } 1120 | 1121 | run(); 1122 | ``` 1123 | 1124 | La gestione degli errori si fa ora con `try...catch`, così: 1125 | 1126 | ```js 1127 | try { 1128 | let content = await readFile('file.txt'); 1129 | return content; 1130 | } 1131 | catch (ex) { 1132 | console.log(ex); 1133 | } 1134 | ``` 1135 | 1136 | ## Come approfondire 1137 | 1138 | La documentazione di MDN per quanto riguarda JavaScript è in generale eccellente. Se vuoi andare in profondità, una lettura consigliata è [questo libro gratuito](https://github.com/getify/You-Dont-Know-JS) che si chiama *You don't know JS*. Esplora l'intero linguaggio JavaScript in modo davvero completo. 1139 | 1140 | Per quanto riguarda il resto, in genere vale la [documentazione di Node.js](https://nodejs.org/dist/latest-v8.x/docs/api/) (attenzione alla versione), e quella dei moduli che usate, ad esempio [Express](http://expressjs.com/) e [request](https://github.com/request/request). 1141 | 1142 | Consiglio anche [questa newsletter settimanale](https://nodeweekly.com/), per restare aggiornato sulle nuove versioni di Node.js e ricevere articoli di approfondimento. 1143 | --------------------------------------------------------------------------------