APIError.js

const httpStatus = require('http-status');

/**
* @extends Error
*/
class ExtendableError extends Error {
    constructor(message, status, isPublic) {
        super(message);
        this.name = this.constructor.name;
        this.message = message;
        this.status = status;
        this.isPublic = isPublic;
        this.isOperational = true; // This is required since bluebird 4 doesn't append it anymore.
        Error.captureStackTrace(this, this.constructor.name);
    }
}

/**
* Class representing an API error.
* @extends ExtendableError
*/
class APIError extends ExtendableError {
    /**
    * Creates an API error.
    * @param {string} message - Error message.
    * @param {number} status - HTTP status code of error.
    * @param {boolean} isPublic - Whether the message should be visible to user or not.
    */
    constructor(message, status = httpStatus.INTERNAL_SERVER_ERROR, isPublic = false) {
        super(message, status, isPublic);
    }
}

module.exports = APIError;

express.js

const httpStatus = require('http-status');


// if error is not an instanceOf APIError, convert it.

app.use((err, req, res, next) => {

    if (err instanceof expressValidation.ValidationError) {

        // validation error contains errors which is an array of error each containing message[]

        const unifiedErrorMessage = err.errors.map(error => error.messages.join('. ')).join(' and ');

        const error = new APIError(unifiedErrorMessage, err.status, true);

        return next(error);

    } else if (!(err instanceof APIError)) {

        const apiError = new APIError(err.message, err.status, err.isPublic);

        return next(apiError);

    }

    return next(err);

});



// catch 404 and forward to error handler

app.use((req, res, next) => {

    const err = new APIError('API not found', httpStatus.NOT_FOUND);

    return next(err);

});

// error handler, send stacktrace only during development

app.use((err, req, res, next) => // eslint-disable-line no-unused-vars

    res.status(err.status).json({

        status: 0,

        errmsg: err.isPublic ? err.message : httpStatus[err.status],

        stack: config.env === 'development' ? err.stack : {}

    })

);

Model层、Service层直接throw APIError

model之间交叉调用时,控制器方法内调用多个model时,需要使用service

Controller层直接next(err)

使用此方法可以使express实现分层

Scroll to Top