Skip to content

Errors handling (from service)

AGenson edited this page Mar 4, 2018 · 4 revisions

Errors handling (from service)

The adapter will manage the format of the response, as described in functions or errors handling.

But you do not especially want your client to see all those formatted responses. So here is an implementation of what could be a modulable solution.


Receiving function response

Responses will be Promises. So the simple way of receiving the response in a service action is:

getAll: {
	params: {

	},
	handler(ctx) {
		return this.DB_Table1.find(ctx)
			.then( (res) => res )
			.catch( (err) => {
				if (err.name === 'Nothing Found')
					return this.requestError(CodeTypes.T1_NOTHING_FOUND);
				else
					return this.requestError(CodeTypes.UNKOWN_ERROR);
			});
	}
}

Result OK

.then( (result) => ...) will enable you to do whatever you want with the result. You can even concatenate several then.

Result Not OK

.catch( (error) => ...) will enable you to handle the error that occured in one of the above Promises.

I recommend adding a console.log(error); while developping to see in the console what really is the problem, else you will be as blind as you want your client to be. If an "Unknown Error" comes from the function, you can also put that line in the function itself (.src/adapters/Database.js), in the catch.


Create client errors

As we said, you do not want your client to know the line and file when the problem occured (for example).

The best way to fix this is to create a switch-case function handling error codes you create. Else it return a default error. You can find this code (./src/mixins/request.mixin.js):

"use strict";

const { MoleculerError } = require("moleculer").Errors;
const CodeTypes = require("../fixtures/error.codes");


// Common methods for request answer to different services
module.exports = {
	methods: {

		requestSuccess(name, message) {
			return {
				name: name,
				message: message,
				code: 200
			};
		},

		requestError(codeError) {
			var message, code;

			switch (codeError) {

				// Errors on Table1

				case CodeTypes.T1_NOTHING_FOUND:
					message = "No entity found in Table1 with the given parameters";
					code = 404;
					break;

				case CodeTypes.T1_FIRST_CONSTRAINT:
					message = "First must be unique: not all entities have been inserted or updated";
					code = 417;
					break;

				case CodeTypes.T1_THIRD_CONSTRAINT:
					message = "Third must be a number";
					code = 417;
					break;

				// Errors on Table2

				case CodeTypes.T2_NOTHING_FOUND:
					message = "No entity found in Table2 with the given parameters";
					code = 404;
					break;

				case CodeTypes.T2_SECOND_CONSTRAINT:
					message = "Second must be a number";
					code = 417;
					break;

				// Errors on Table1 & Table2

				case CodeTypes.T1_T2_NOTHING_FOUND:
					message = "Table1 or Table2 is empty";
					code = 404;
					break;

				// Unknown Error

				default:
					message = "Operation failed internally: unknown details";
					code = 500;
					break;
			}

			return this.Promise.reject(new MoleculerError(codeError, code, "ERR_CRITIAL", { code: code, message: message }));
		}
	}
};

And the error codes (./src/fixtures/error.codes):

// All strings must be different
module.exports = {
	// Errors on Table1
	T1_NOTHING_FOUND: "Table1: Nothing Found",
	T1_FIRST_CONSTRAINT: "Invalid First",
	T1_THIRD_CONSTRAINT: "Invalid Third",

	// Errors on Table2
	T2_NOTHING_FOUND: "Table2: Nothing Found",
	T1_SECOND_CONSTRAINT: "Invalid Second",

	// Errors on Table1 & Table2
	T1_T2_NOTHING_FOUND: "Nothing Found",

	// Unknown Error
	UNKOWN_ERROR: "Unknown Error"
};

Then you import it to all the services that needs it, by the way of merging algorith with mixins:

"use strict";

const Database = require("../adapters/Database");
const Request = require("../mixins/request.mixin");
const CodeTypes = require("../fixtures/error.codes");

const Filters_T1 = { ... };


module.exports = {
	name: "service",

	mixins: [ Request ],

    ...
}

You can also format positive response to your client the same way with a requestSuccess(...). In this template it is created, but not implemented.