Ricerca…


Gestione dell'eccezione in Node.Js

Node.js ha 3 modi di base per gestire eccezioni / errori:

  1. prova - cattura blocco
  2. errore come primo argomento di un callback
  3. emit un evento di errore utilizzando eventEmitter

try-catch è usato per catturare le eccezioni generate dall'esecuzione del codice sincrono. Se il chiamante (o il chiamante del chiamante, ...) utilizza try / catch, allora possono rilevare l'errore. Se nessuno dei chiamanti ha tentato di intercettarlo, il programma si blocca.
Se si utilizza try-catch su un'operazione asincrona, è stata generata un'eccezione dal richiamo del metodo asincrono che non verrà catturata da try-catch. Per catturare un'eccezione dalla richiamata dell'operazione asincrona, è preferibile utilizzare le promesse .
Esempio per capirlo meglio

// ** Example - 1  **
function doSomeSynchronousOperation(req, res) {
    if(req.body.username === ''){
        throw new Error('User Name cannot be empty');
    }  
    return true;  
}

// calling the method above
try {
    // synchronous code   
    doSomeSynchronousOperation(req, res)    
catch(e) {
    //exception handled here   
    console.log(e.message);  
} 

// ** Example - 2 **
function doSomeAsynchronousOperation(req, res, cb) {
    // imitating async operation
    return setTimeout(function(){
        cb(null, []);
    },1000);
}
 
try {
    // asynchronous code   
    doSomeAsynchronousOperation(req, res, function(err, rs){
        throw new Error("async operation exception");
    })   
} catch(e) {
     // Exception will not get handled here
     console.log(e.message);  
}
// The exception is unhandled and hence will cause application to break

le callback sono utilizzate principalmente in Node.js in quanto il callback consegna un evento in modo asincrono. L'utente ti passa una funzione (il callback) e la invochi più tardi quando l'operazione asincrona viene completata.
Lo schema normale è che la richiamata è invocata come callback (err, risultato) , dove solo uno di err e result è non nullo, a seconda che l'operazione abbia avuto esito positivo o negativo.

function doSomeAsynchronousOperation(req, res, callback) {
   setTimeout(function(){
        return callback(new Error('User Name cannot be empty'));    
   }, 1000);  
   return true;
}

doSomeAsynchronousOperation(req, res, function(err, result) {
   if (err) {
       //exception handled here 
       console.log(err.message);
   }
   
   //do some stuff with valid data
});

emetta Per i casi più complicati, invece di utilizzare una richiamata, la funzione stessa può restituire un oggetto EventEmitter e il chiamante dovrebbe ascoltare gli eventi di errore sull'emettitore.

const EventEmitter = require('events');

function doSomeAsynchronousOperation(req, res) {
    let myEvent = new EventEmitter();

    // runs asynchronously
    setTimeout(function(){
        myEvent.emit('error', new Error('User Name cannot be empty'));
    }, 1000);

    return myEvent;
}

// Invoke the function
let event = doSomeAsynchronousOperation(req, res);

event.on('error', function(err) {
    console.log(err);
});

event.on('done', function(result) {
    console.log(result); // true
});

Gestione delle eccezioni non gestita

Poiché Node.js viene eseguito su un singolo processo, le eccezioni non rilevate sono un problema da tenere presente quando si sviluppano applicazioni.

Eccezioni di gestione silenziosa

La maggior parte delle persone lascia che i server node.js soppongano silenziosamente gli errori.

  • Gestendo in silenzio l'eccezione
process.on('uncaughtException', function (err) {
  console.log(err);
});

Questo è male , funzionerà ma:

  • La causa principale rimarrà sconosciuta, in quanto tale non contribuirà alla risoluzione di ciò che ha causato l'eccezione (errore).

  • Nel caso in cui la connessione al database (pool) venga chiusa per qualche motivo, ciò comporterà una costante propagazione degli errori, il che significa che il server sarà in esecuzione ma non si riconnetterà a db.


Ritorno allo stato iniziale

In caso di "uncaughtException" è bene riavviare il server e riportarlo allo stato iniziale , dove sappiamo che funzionerà. Viene registrata un'eccezione, l'applicazione viene chiusa ma, poiché verrà eseguita in un contenitore che si accerterà che il server sia in esecuzione, otterremo il riavvio del server (ritorno allo stato operativo iniziale).

  • Installazione per sempre (o altro strumento CLI per assicurarsi che quel server nodo funzioni continuamente)
npm install forever -g
  • Avvio del server per sempre
forever start app.js

Il motivo per cui è stato avviato e il motivo per cui utilizziamo per sempre è dopo che il server è stato interrotto per sempre. Il processo riavvierà il server.

  • Riavvio del server
process.on('uncaughtException', function (err) {
    console.log(err);

    // some logging mechanisam
    // ....        

    process.exit(1); // terminates process
});

In una nota a margine c'era anche un modo per gestire le eccezioni con Cluster e Domini .

I domini sono deprecati qui più informazioni.

Errori e promesse

Le promesse gestiscono gli errori in modo diverso rispetto al codice sincrono o callback.

const p = new Promise(function (resolve, reject) {
    reject(new Error('Oops'));
});

// anything that is `reject`ed inside a promise will be available through catch
// while a promise is rejected, `.then` will not be called
p
    .then(() => {
        console.log("won't be called");
    })
    .catch(e => {
        console.log(e.message); // output: Oops
    })
    // once the error is caught, execution flow resumes
    .then(() => {
        console.log('hello!'); // output: hello!
    });

attualmente, gli errori generati da una promessa che non viene rilevata provocano l'errore di essere ingeriti, il che può rendere difficile rintracciare l'errore. Questo può essere risolto utilizzando strumenti di linting come eslint o assicurando di avere sempre una clausola di catch .

Questo comportamento è deprecato nel nodo 8 a favore del termine del processo del nodo.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow