用于记录错误的适当代码设计

问题描述 投票:0回答:1

我正在编写一个将通过Google Cloud Functions作为API公开的函数。它获取用户坐标,通过API查找位置名称,然后使用该信息调用另一个API,然后返回该数据。

我的问题是如何最好地处理错误。到目前为止,我已经实现了以下代码中所述的内容,但是我不确定它是好的还是“正确的” ...

// index.js

const { getCityByLatLon } = require('./location.js');
const { getWeatherByCity } = require('./weather.js');

module.exports.getWeather = async (req, res) => {
  try {
    // Validate request - implementation not important
  } catch (e) {
    // Don't care about logging bad input anywhere, just send error to consumer
    return res.status(422).json({ error: e.message });
  }

  const { lat, lon } = req.query;

  try {
    const city = await getCityByLatLon(lat, lon);
    const weather = await getWeatherByCity(city);
    res.json(weather);
  } catch (e) {
    // Need to return an error here...
    // Should it be the message that either getCityByLatLon or getWeatherByCity
    // gives, or should it be handled a different way?
    res.status(500).json({ error: e.message });
  }
};

// location.js

module.exports.getCityByLatLon = (lat, lon) => {
    const mapsClient = new Client(); // Implementation not important

    try {
        const result = await mapsClient.reverseGeocode(lat, lon);

        if (result.status !== 'OK') {
            // We can't handle this, but should log it and tell the caller
            // that something went wrong
            throw new Error(result.error_message);
        }

        if (result.data.length < 1) {
            throw new Error('No results');
        }

        return result.data[0].city;
    } catch (e) {
        // I think I want to log this exception and store it somewhere
        logger.log(e);

        // And throw a "nice" error which doesn't give info on the underlying
        // error, for the API response to return
        throw new Error('Failed to get City');
    }
};

// weather.js

module.exports.getWeatherByCity = (city) => {
    const weatherClient = new Client(); // Implementation not important

    try {
        const result = await weatherClient.fetchNextWeek(city);

        if (result.status !== 'OK') {
            // We can't handle this, but should log it and tell the caller
            // that something went wrong
            throw new Error(result.error_message);
        }

        return result.data;
    } catch (e) {
        // I think I want to log this exception and store it somewhere
        logger.log(e);

        // And throw a "nice" error which doesn't give info on the underlying
        // error, for the API response to return
        throw new Error('Failed to get Weather');
    }
};

这真的是一个好习惯吗?我认为可能是因为getCityByLatLongetWeatherByCity没有暴露具体实现错误。但是,WebStorm通过显示检查('throw' of exception caught locally)使我再次考虑,因为我正在throw块中try,然后立即对其进行处理。

javascript node.js api structure code-design
1个回答
0
投票

常见方法应该是将错误传递给链中最顶层的函数,这有助于实现干净的代码,并避免代码中出现太多try/catch。在您的情况下,由于功能可能会失败,因此调用者有责任记录消息。向每个函数添加一条日志语句并不理想,因为它可能导致重复的错误消息出现在您的日志记录系统中。

考虑到调用者也在catch块内打印错误的情况,在这种情况下,错误在控制台中被打印两次。

常见的方法是抛出错误,并让调用者决定如何处理错误。

一种更常见且更可靠的方法是在请求路由器中添加错误中间件,以处理系统中的错误记录。您可以按如下所示将错误的中间件附加到快递请求路由器:

import { Router } from "express";
const router = Router();
// ... your routes in the format router("/").get()
router.use((err, req, res, next) => {
   // we have got an error, we can log it
   console.log(err);
   res.status(500).json({ error: e.message });
});

现在,在您的控制器中,您可以使用类似这样的内容

module.exports.getWeather = async (req, res, next) => {
  try {
    // Validate request - implementation not important
  } catch (e) {
    // Don't care about logging bad input anywhere, just send error to 
    consumer
    return res.status(422).json({ error: e.message });
  }

  const { lat, lon } = req.query;
  try {
    const city = await getCityByLatLon(lat, lon);
    const weather = await getWeatherByCity(city);
    res.json(weather);
  } catch (e) {
    // Need to return an error here...
    // Should it be the message that either getCityByLatLon or 
    getWeatherByCity
    // gives, or should it be handled a different way?
    return next(err); // this forces your design to use only one type of response payload for all kind of 500 errors. The schema of your object remains the same. Also, your errors will get logged as well.
  }
};
© www.soinside.com 2019 - 2024. All rights reserved.