Qual seria a melhor abordagem para o tratamento de erros no Node?

Opa, estou com uma dúvida sobre qual seria a melhor abordagem para o tratamento de erros n a minha aplicação. Vou expor minha dúvida, como estou resolvendo-a, e como eu acho que poderia ser.

Bem, vamos lá:

Eu tenho uma função inicial a start(), que espera a resposta de outra função. Escrevi ela desta forma:

async function start() {
    try {
        if (...) {
            ...
            await read(...);
        } else {
            throw new Error('(COD001)');
        }
    } catch (error) {
        recordLog(error);
    }
}

Já a função read() (que se encontra em outro arquivo) escrevi desta forma:

async function read(folder, profile) {
    try {
        const result = await readFolder(folder)
            .then(...)
            .then(...);
        return result;
    } catch (error) {
        if (error.message.includes('(COD002)')) {
            throw error;
        } else {
            error.message = '(COD003)';
            throw error;
        }
    }
}

Minha intenção aqui era a seguinte, se o erro ocorresse em readFolder(), eu iria propagar este erro para a função start(), senão, propagaria o outro erro.

Para fechar, em readFolder() (que também encontra-se em outro arquivo), eu escrevi assim:

function readFolder(folder) {
    return new Promise((resolve, reject) => {
        try {
            ...
            resolve(result);
        } catch (error) {
            error.message = '(COD002)';
            reject(error);
        }
    });
}

Entretanto estou achando esta abordagem confusa, pois eu tenho diversas funções, ou seja, terei que fazer vários ifs para saber onde o erro ocorreu e então propagar este erro para a função start().

Bem, penso que poderia existir algo como um "estado de erro global", para capturar o erro em qualquer parte da aplicação e encaminhar este erro diretamente para a função start().

Será que existe alguma funcionalidade no Node ou alguma biblioteca que faça isso? Senão, esta abordagem que estou adotando é a mais correta?

Valeu pela ajuda pessoal,

Muito obrigado. Lucas.

Acho que entendi, você parece estar usando um padrão chamado "action" https://dev.to/urielsouza29/padrao-por-acao-action-pattern-limpo-obvio-e-testavel-3j7d

Esse padrão do texto é parecido com o seu, mas melhor organizado. Se você gosta do seu modo complementar com o action vai te ajuda muito mais!

const validateOptions = (options) => {
  try {
    if (!options) throw new Error('options object is required.');
    if (!options.someOption) throw new Error('options.someOption is required.');
  } catch (exception) {
    throw new Error(`[validateOptions] ${exception.message}`);
  }
}; 

Eu sugeriria mais uma complementação ao action. usar

Usar o error cause

https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Error/cause

const validateOptions = (options) => {
  try {
    if (!options) throw new Error('options object is required.');
    if (!options.someOption) throw new Error('options.someOption is required.');
  } catch (exception) {
  
    throw new Error('[validateOptions]', { cause: { code: COD002 , message:exception.message }, });
  }
}; 

Você não precisa sempre de try catch para mandar um erro. Pode ser só if mesmo!

Você também pode centralizar os erros num lugar só!

https://www.toptal.com/nodejs/node-js-error-handling

Mais um pouco sobre como lidar com erros! https://kinsta.com/blog/errors-in-javascript/

Espero que isso ajude!