Fibre di nodo e richiamate asincrone
di Neil Lobo, Ingegnere del software
Parte della popolarità di Node.js è il ciclo di eventi. Piuttosto che adottare l'approccio multithreaded dei framework tradizionali, Node.js utilizza un modello di I/O non bloccante e guidato dagli eventi. Questo gli conferisce un'impronta di memoria più leggera, è più leggero ed efficiente, e si bilancia bene per applicazioni in tempo reale ad alta intensità di dati.
Questo approccio non di blocco guidato dagli eventi funziona bene per le applicazioni in cui il collo di bottiglia è l'attività di I/O o di rete. Al contrario, se l'applicazione richiede compiti intensivi di CPU, allora Node.js è probabilmente una scelta sbagliata.
Tuttavia, lavorare con Node.js nudo richiede l'uso di richiamate asincrone che portano al famigerato inferno delle richiamate. Questo porta ad una logica difficile da seguire
//Callback Soup/Spiral Callback of Doom function doAsync1(function () { doAsync2(function () { doAsync3(function () { doAsync4(function () { //finally do something }); }); }); });
La gestione degli errori e i richiami annidati sono scomodi da scrivere, e la loro esistenza rende il codice difficile da mantenere e da scalare. Ci sono alcune tecniche per superare questi problemi, le più popolari sono Fibre e Promesse. Voglio discutere la prima come Meteor usa Fibers per ottenere un codice sincrono come quello del ciclo di eventi.
Fibre
Per coloro che non hanno familiarità con esso, Fibers è un costrutto informatico che utilizza un modello di multitasking cooperativo (a differenza dei fili utilizzano il multitasking preventivo)
Il codice threaded può essere interrotto in qualsiasi punto, anche nel bel mezzo della valutazione di un'espressione, per dare cicli di CPU al codice in esecuzione in un altro thread. Con le fibre, queste interruzioni e gli switch di contesto non sono determinati dalla CPU o da un processo di livello inferiore; sono determinati dal programmatore che decide dove il suo codice cederà e darà cicli di CPU ad altre fibre.
Ecco un esempio di codice tipico di Node.js che utilizza una funzione di callbackFunction che viene passato il risultato.
getDataFromDisk = function(fileName, key, callbackFunction) {
var risultato;
fs.readFile('/path/fileName', function(err, res) { if (err) console.log(err); else { result = transform(res, key); callbackFunction(result); }}};
Cerchiamo di scrivere questo in uno stile più sincrono
getDataFromDisk = function(fileName, key) { var result; fs.readFile('/path/fileName', function(err, res) { if (err) console.log(err); else result = transform(res, key);
} il risultato di ritorno;// sarà sempre indefinito }; // Cerchiamo di usare getDataFromDisk per restituire il valore, quindi // stamparlo, tutto in modo sincrono. var result = getDataFromDisk('helloWorld',chiave); console.log(risultato); // non definito
Il codice di cui sopra restituirà sempre indefinito, in quanto il ciclo dell'evento passerà alla linea del risultato di ritorno (*) senza attendere il risultato del richiamo.
Utilizzo delle fibre
Le fibre sono una classe di funzioni del contenitore che possono essere utilizzate per bloccare una sotto-routine in attesa di qualche attività di I/O o di rete senza bloccare l'intero processo.
var Fiber = Npm.require('fibers');// getDataFromDisk function using Fibers getDataFromDisk = function(filename, key) {var fiber = Fiber.current; //get the current Fiber fs.readFile('/path/fileName', function(err, res) { if (err) console.log(err); else{ /* Resume execution of this fiber. What’s passed to fiber.run will become the value returned by Fiber.yield below */ fiber.run( transform(res, key) ); var result = Fiber.yield(); return result;}; // Finally we wrap our code in a Fiber, then run it Fiber(function() {
var result = getDataFromDisk('helloWorld', chiave); console.log(risultato); })).run();
Presto, abbiamo un codice dall'aspetto sincrono che viene ancora eseguito in modo asincrono sul loop degli eventi.
Per maggiori dettagli su Fibre controllate (https://github.com/laverdet/node-fibers)