乐闻世界logo
搜索文章和话题

Detailed explanation of Koa error handling mechanism and best practices

2月21日 15:53

Koa's error handling mechanism is very elegant, providing multiple error handling methods through try-catch and event systems. Proper error handling is key to building robust applications.

1. Using ctx.throw() to throw errors:

javascript
app.use(async (ctx) => { if (!ctx.query.token) { ctx.throw(401, 'Token is required'); } ctx.body = 'Success'; });

2. Using try-catch to catch errors:

javascript
app.use(async (ctx, next) => { try { await next(); } catch (err) { ctx.status = err.status || 500; ctx.body = { error: err.message, code: err.code || 'INTERNAL_ERROR' }; ctx.app.emit('error', err, ctx); } });

3. Error handling middleware:

javascript
async function errorHandler(ctx, next) { try { await next(); } catch (err) { ctx.status = err.status || 500; // Return detailed error info in development if (app.env === 'development') { ctx.body = { error: err.message, stack: err.stack, code: err.code }; } else { // Return simplified error info in production ctx.body = { error: 'Internal Server Error', code: 'INTERNAL_ERROR' }; } // Trigger application error event ctx.app.emit('error', err, ctx); } } app.use(errorHandler);

4. Custom error classes:

javascript
class AppError extends Error { constructor(status, message, code) { super(message); this.status = status; this.code = code; this.name = 'AppError'; } } class NotFoundError extends AppError { constructor(message = 'Resource not found') { super(404, message, 'NOT_FOUND'); this.name = 'NotFoundError'; } } class ValidationError extends AppError { constructor(message = 'Validation failed') { super(400, message, 'VALIDATION_ERROR'); this.name = 'ValidationError'; } } // Use custom errors app.use(async (ctx) => { const user = await findUser(ctx.params.id); if (!user) { throw new NotFoundError('User not found'); } ctx.body = user; });

5. Global error listening:

javascript
app.on('error', (err, ctx) => { // Log error console.error('Server error:', err); // Send error notification (email, Slack, etc.) sendErrorNotification(err, ctx); // Report to monitoring system reportToMonitoring(err, ctx); });

6. 404 handling:

javascript
// Add 404 handling after all routes app.use(async (ctx) => { ctx.status = 404; ctx.body = { error: 'Not Found', code: 'NOT_FOUND', path: ctx.url }; });

7. Async error handling:

javascript
// Koa automatically catches errors in async functions app.use(async (ctx) => { const data = await fetchData(); // If this throws, it will be caught ctx.body = data; }); // For Promise chains, ensure proper handling app.use(async (ctx) => { try { const result = await someAsyncOperation() .then(data => processData(data)) .catch(err => { throw new AppError(400, 'Processing failed', 'PROCESS_ERROR'); }); ctx.body = result; } catch (err) { ctx.throw(err.status || 500, err.message); } });

8. Error handling best practices:

javascript
// Complete error handling example const Koa = require('koa'); const app = new Koa(); // Custom error class class AppError extends Error { constructor(status, message, code) { super(message); this.status = status; this.code = code; } } // Error handling middleware app.use(async (ctx, next) => { try { await next(); } catch (err) { // Set status code ctx.status = err.status || 500; // Build error response const errorResponse = { error: err.message, code: err.code || 'INTERNAL_ERROR', timestamp: new Date().toISOString() }; // Include stack info in development if (app.env === 'development') { errorResponse.stack = err.stack; } ctx.body = errorResponse; // Trigger error event ctx.app.emit('error', err, ctx); } }); // Global error listening app.on('error', (err, ctx) => { console.error(`[${new Date().toISOString()}] Error:`, err.message); console.error('Path:', ctx.url); console.error('Stack:', err.stack); }); // Business routes app.use(async (ctx) => { if (ctx.path === '/error') { throw new AppError(500, 'Something went wrong', 'SERVER_ERROR'); } if (ctx.path === '/not-found') { ctx.throw(404, 'Resource not found'); } ctx.body = 'Hello Koa'; }); app.listen(3000);

9. Common error handling scenarios:

javascript
// Database error handling app.use(async (ctx, next) => { try { await next(); } catch (err) { if (err.code === '23505') { // PostgreSQL unique constraint violation ctx.throw(409, 'Resource already exists'); } else if (err.code === '23503') { // Foreign key constraint violation ctx.throw(400, 'Invalid reference'); } else { throw err; } } }); // Validation error handling app.use(async (ctx, next) => { try { await next(); } catch (err) { if (err.name === 'ValidationError') { ctx.throw(400, err.message); } throw err; } });

Error handling key points:

  1. Use try-catch to wrap code that might fail
  2. Create custom error classes for clearer error information
  3. Distinguish between development and production error responses
  4. Implement global error listening for unified logging and reporting
  5. Provide appropriate HTTP status codes for different error types
  6. Ensure errors don't leak sensitive information
  7. Add error handling middleware at the outermost layer of the onion model
标签:Koa