2015-10-19 6 views
0

В следующем коде, когда переменная err возвращается из функции обратного вызова deleteUser Я хочу вставить эту ошибку в базу данных и завершить HTTP-запрос (и весь этот блок кода) с помощью return res.send(500).Выход из серии вложенных обратных вызовов

Вместо этого код продолжает работать и вызывается db.destroy, хотя HTTP-запрос уже завершен. Об этом свидетельствуют журналы в нижней части сообщения.

// DELETE 
app.del('/api/users', function(req, res) { 
    var id = req.query.id; 

    // get latest copy of database entry first, in case we need to save error message 
    db.get(id, {revs_info: true}, function(err, doc) { 
     if (err) { 
      console.error('Unable to find document', id, 'due to:', err); 
      return res.send(500); 
     } else { 
      // issue delete request first, if fails save error message 
      deleteUser(doc.EmailAddress, function(err) { 
       if (err) { 
        // update database with error message (if there's already a message, append) 
        doc.Notes = (doc.Notes === '') ? err : err + " " + doc.Notes; 

        db.insert(doc, function(err, document) { 
         if(err) { 
          console.error('Deleting a user failed (1) and updating database with error status failed (2) as well. 1:', doc.Notes, '2:', err); 
          return res.send(500); 
         } else { 
          console.error('Deleting a user failed (with the following) and the error has been stored in the database:', doc.Notes); 
          return res.send(500); 
         } 
        }); 
       } 

       // proceed to delete from database as well 
       db.destroy(doc._id, doc._rev, function (err, body) { 
        if(err) { 
         console.error('Error deleting document', doc._id, 'with:', err); 
         return res.send(500); 
        } else { 
         if (doc._revs_info) delete doc._revs_info; 
         console.log('Succesfully deleted user from system and our database:', doc); 
         return res.send(200); 
        } 
       }); 
      }); 
     } 
    }); 
}); 

Я предполагаю, что это происходит потому, что мой return оператор только заканчивает функцию db.insert.

Существует ли общий шаблон проектирования для решения этой проблемы в узле?

Должен ли я просто добавить еще один оператор return после объявления db.insert, но до окончания блока кода if (err) {?

Бревна после выдачи запроса DELETE к моему экземпляру сервера:

Deleting a user failed (with the following) and the error has been stored in the database: POST 500 has returned an error. 

127.0.0.1 - - [Mon, 19 Oct 2015 02:50:19 GMT] "DELETE /api/users?id=11 HTTP/1.1" 500 21 "http://localhost:3000/" "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:41.0) Gecko/20100101 Firefox/41.0" 

Succesfully deleted user from system and our database: { _id: '11', 
    _rev: '3-e6fec584448d664476ddaf3b7e150cd7', 
    EmailAddress: '[email protected]', 
    Status: 0, 
    Notes: 'POST 500 has returned an error.' } 

ответ

2

Во-первых, да, добавьте return заявление перед закрытием if() {}. Это важно.

Во-вторых, ваш код страдает callback hell, и вам стоит серьезно подумать о переходе на более «современную» альтернативу, мой личный фаворит - обещание. Here's a great article about this.

Для узла, попробуйте посмотреть на bluebird или es6-promisify

0

Вы можете ввести флаг ошибки где-то высоко, который по умолчанию ложно:

var bFatalError = false; 

Везде, где вы обнаружили фатальную ошибку вы установите этот флаг перед возвращением:

bFatalError = true; 

и в верхней части каждого блока кода вы можете проверить-и-аборт, если флаг установлен:

if (bFatalError) { return; } 

Таким образом, вы сигнализируете, что другой код не запускается.

Смежные вопросы