Поиск…


Исправление обработки в Node.Js

Node.js имеет 3 основных способа обработки исключений / ошибок:

  1. блок try- catch
  2. ошибка в качестве первого аргумента для callback
  3. emit событие ошибки с помощью eventEmitter

try-catch используется для обнаружения исключений, возникающих при выполнении синхронного кода. Если вызывающий (или вызывающий абонент, ...) использовал try / catch, то они могут поймать ошибку. Если ни один из вызывающих абонентов не имеет попыток, чем программа выйдет из строя.
Если использование try-catch в async-операции и исключение было выбрано из обратного вызова метода async, то оно не попадет в try-catch. Чтобы поймать исключение из обратного вызова асинхронной операции, предпочтительно использовать обещания .
Пример, чтобы лучше понять его

// ** 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

обратные вызовы в основном используются в Node.js, поскольку обратный вызов выполняет асинхронное событие. Пользователь передает вам функцию (обратный вызов), и вы вызываете ее когда-нибудь позже, когда асинхронная операция завершается.
Обычная модель заключается в том, что обратный вызов вызывается как обратный вызов (ошибка, результат) , где только один из ошибок и результатов не равен нулю, в зависимости от того, была ли операция успешной или неудачной.

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
});

emit Для более сложных случаев вместо использования обратного вызова сама функция может возвращать объект EventEmitter, и ожидается, что вызывающий абонент будет прослушивать события ошибки на эмиттере.

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
});

Управление незатронутыми исключениями

Поскольку Node.js работает на одном процессе, неработающие исключения - это проблема, о которой следует знать при разработке приложений.

Без исключения

Большинство людей позволяют серверу (узлам) node.js незаметно проглатывать ошибки.

  • Тишина обработки исключения
process.on('uncaughtException', function (err) {
  console.log(err);
});

Это плохо , он будет работать, но:

  • Корневая причина остается неизвестной, так как это не будет способствовать разрешению того, что вызвало исключение (ошибка).

  • В случае, если соединение с базой данных (пул) закрывается по какой-либо причине, это приведет к постоянному распространению ошибок, что означает, что сервер будет работать, но он не будет повторно подключаться к db.


Возврат в начальное состояние

В случае «uncaughtException» хорошо перезапустить сервер и вернуть его в исходное состояние , где мы знаем, что он будет работать. Исключение регистрируется, приложение завершается, но поскольку он будет запущен в контейнере, который будет следить за тем, чтобы сервер работал, мы достигнем перезапуска сервера (вернемся к исходному рабочему состоянию).

  • Установка вечно (или другого инструмента CLI, чтобы убедиться, что сервер узла работает непрерывно)
npm install forever -g
  • Запуск сервера навсегда
forever start app.js

Причина, почему она началась и почему мы используем вечно, - это то, что сервер будет завершен навсегда, и процесс снова запустит сервер.

  • Перезапуск сервера
process.on('uncaughtException', function (err) {
    console.log(err);

    // some logging mechanisam
    // ....        

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

На стороне заметки был также способ обработки исключений с кластерами и доменами .

Домены больше не рекомендуют здесь .

Ошибки и обещания

Обещания обрабатывают ошибки по-разному для синхронного или обратного кода.

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!
    });

в настоящее время ошибки, сбрасываемые в обещание, которое не попало, приводят к проглатыванию ошибки, что может затруднить отслеживание ошибки. Это можно решить, используя инструменты linting, такие как eslint, или гарантируя, что вы всегда имеете предложение catch .

Это поведение устарело в узле 8 в пользу прекращения процесса узла.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow