javascript - Mongo db con Monk: error de captura y manejo si db está abajo
node.js mongodb (1)
Soy nuevo en Mongo. Necesitaba una base de datos para un proyecto simple y terminé siguiendo un tutorial usando Mongo con Monk, pero tengo problemas para entender cómo manejar los errores.
Antecedentes : tengo un formulario de registro en el lado del cliente. Cuando el usuario hace clic en un botón, los datos se envían a través de AJAX al controlador que (tras la validación, pero esto no es relevante ahora) inserta dichos datos en la base de datos y devuelve el éxito o el error. Cuando la base de datos está activa, todo parece funcionar bien.
El problema : si no inicio el DB e intento enviar la solicitud de todos modos, no se devuelve ningún error. Simplemente no pasa nada. Después de un tiempo en la consola obtengo: POST / members / addmember - - ms - - .
Creo que debería devolverse algún error al usuario en este caso, entonces, ¿cómo podría hacer esto?
La solicitud posterior está debajo (más o menos como en el tutorial):
// app.js
var db = monk(''localhost:27017/dbname'')
[...]
// I realize it might be not optimal here
app.use(function(req,res,next){
req.db = db;
next();
});
// members.js
router.post(''/addmember'', function(req, res) {
var db = req.db;
var collection = db.get(''memberstest'');
collection.insert(req.body, function(err, result){
res.json(
(err === null) ? { msg: ''success'' } : { msg: err }
);
});
});
Si la base de datos está inactiva, creo que el problema es incluso anterior a la inserción, es decir, " db.get () ". Entonces, ¿cómo verificar si eso realmente se puede hacer? Supongo que dada la naturaleza asíncrona del nodo algo así como un try / catch sería inútil aquí. ¿Correcto?
EDITAR: Después de la respuesta de Neil y un poco de intentarlo, armé lo siguiente que parece hacer el trabajo. Sin embargo, dado mi escaso grado de confianza en esto, agradecería un comentario si el siguiente código funciona porque tiene sentido o por casualidad. Agregué las opciones de bufferMaxEntries: 0 y modifiqué el controlador de la siguiente manera. En la devolución de llamada ajax, simplemente tengo una alerta por ahora que muestra el mensaje de error lanzado (si corresponde).
router.post(''/addmember'', async (req,res) => {
try {
let db = req.db;
let collection = db.get(''memberstest'');
collection.insert(req.body, function(err, result){
res.json(
(err === null) ? { msg: ''success'' } : { msg: err }
);
});
await db.then(() => 1);
} catch(e) {
res.json({msg: e.message})
}
});
Bueno, puedes establecer la opción bufferMaxEntries
(documentada en Db
pero obsoleta para el uso de ese objeto, usarla en "nivel superior como se demostró en su lugar") en la conexión, lo que básicamente detiene las solicitudes de "cola" en el controlador cuando no hay conexión presente.
Como un ejemplo mínimo:
index.js
const express = require(''express''),
morgan = require(''morgan''),
db = require(''monk'')(''localhost/test'',{ bufferMaxEntries: 0 }),
app = express();
const routes = require(''./routes'');
app.use(morgan(''combined''));
app.use((req,res,next) => {
req.db = db;
next();
});
app.use(''/'', routes);
(async function() {
try {
await db.then(() => 1);
let collection = db.get(''test'');
await collection.remove({});
await collection.insert(Array(5).fill(1).map((e,i) => ({ a: i+1 })));
console.log(''inserted test data'');
await app.listen(3000,''0.0.0.0'');
console.log(''App waiting'');
} catch(e) {
console.error(e);
}
})();
routes.js
var router = require(''express'').Router();
router.get(''/'', async (req,res) => {
try {
let db = req.db,
collection = db.get(''test'');
let response = await collection.find();
res.json(response);
} catch(e) {
res.status(500).json(e);
}
});
module.exports = router;
Así que en realidad estoy esperando que la conexión de la base de datos esté presente al menos en "inicio" aquí, pero realmente solo por ejemplo, ya que quiero insertar algunos datos para recuperarlos realmente. No es obligatorio, pero el concepto básico es esperar a que la Promise
resuelva:
await db.then(() => 1);
Es algo trivial, y no es realmente necesario para tu código real. Pero todavía creo que es una buena práctica.
La prueba real se realiza deteniendo mongod
o haciendo que el servidor no sea accesible y luego emitiendo una solicitud.
Dado que establecemos las opciones de conexión en { bufferMaxEntries: 0 }
esto significa que inmediatamente cuando intente emitir un comando a la base de datos, la falla se devolverá si no hay una conexión real presente.
Por supuesto, cuando la base de datos vuelva a estar disponible, no obtendrá el error y las instrucciones se realizarán normalmente.
Sin la opción, el valor predeterminado es "poner en cola" las operaciones hasta que se resuelva una conexión y luego el "buffer" se "reproduce" esencialmente.
Puede simular esto (como lo hice yo) "parando" el daemon mongod
y emitiendo solicitudes. Luego "iniciando" el daemon y emitiendo solicitudes. Simplemente debería devolver la respuesta de error capturada.
NOTA : No es obligatorio, pero de hecho todo el propósito de la sintaxis
async/await
try..catch
es hacer que cosas comotry..catch
válidas nuevamente, ya que en realidad se puede usar como bloques en lugar de usarPromise.catch()
oerr
argumentos de devolución de llamada para atrapar el errores Los mismos principios se aplican cuando cualquiera de esas estructuras está realmente en uso.