title: Handling errors in Express.js in service / controller layers
body: <p>I am writing an application in Express.js with a separate controller layer and a service layer. Here is my current code:</p>
  
  <p><strong>user.service.js</strong></p>
  
  <pre><code>exports.registerUser = async function (email, password) {
    const hash = await bcrypt.hash(password, 10);
    const countUser = await User.countDocuments({email: email});
    if(countUser &gt; 0) {
      throw ({ status: 409, code: 'USER_ALREADY_EXISTS', message: 'This e-mail address is already taken.' });
    }
    const user = new User({
      email: email,
      password: hash
    });
    return await user.save();
  };
  
  exports.loginUser = async function (email, password) {
    const user = await User.findOne({ email: email });
    const countUser = await User.countDocuments({email: email});
    if(countUser === 0) {
      throw ({ status: 404, code: 'USER_NOT_EXISTS', message: 'E-mail address does not exist.' });
    }
    const validPassword = await bcrypt.compare(password, user.password);
    if (validPassword) {
      const token = jwt.sign({ email: user.email, userId: user._id }, process.env.JWT_KEY, { expiresIn: "10s" });
      return {
        token: token,
        expiresIn: 3600,
        userId: user._id
      }
    } else {
      throw ({ status: 401, code: 'LOGIN_INVALID', message: 'Invalid authentication credentials.' });
    }
  };
  </code></pre>
  
  <p><strong>user.controller.js</strong></p>
  
  <pre><code>exports.userRegister = async function (req, res, next) {
    try {
      const user = await UserService.registerUser(req.body.email, req.body.password);
      res.status(201).json({ data: user });
    } catch (e) {
      if(!e.status) {
        res.status(500).json( { error: { code: 'UNKNOWN_ERROR', message: 'An unknown error occurred.' } });
      } else {
        res.status(e.status).json( { error: { code: e.code, message: e.message } });
      }
    }
  }
  
  exports.userLogin = async function (req, res, next) {
    try {
      const user = await UserService.loginUser(req.body.email, req.body.password);
      res.status(200).json({ data: user });
    } catch (e) {
      if(!e.status) {
        res.status(500).json( { error: { code: 'UNKNOWN_ERROR', message: 'An unknown error occurred.' } });
      } else {
        res.status(e.status).json( { error: { code: e.code, message: e.message } });
      }
    }
  }
  </code></pre>
  
  <p>The code works, but requires some corrections. I have a problem with error handling. I want to handle only some errors. If another error has occurred, the 500 Internal Server Error will be returned.</p>
  
  <p>1) Can I use "throw" object from the service layer? Is this a good practice?</p>
  
  <p>2) How to avoid duplication of this code in each controller:</p>
  
  <pre><code>if(!e.status) {
      res.status(500).json( { error: { code: 'UNKNOWN_ERROR', message: 'An unknown error occurred.' } });
  } else {
      res.status(e.status).json( { error: { code: e.code, message: e.message } });
  }
  </code></pre>
  
  <p>3) Does the code require other corrections? I'm just learning Node.js and I want to write the rest of the application well.</p>