节点 Sqlite3 错误

Node Sqlite3 Errors

我在节点中使用 sqlite3 包并开始清除我的 REST API。我决定围绕数据库调用和控制器创建一个承诺包装器,使用 async/await 调用这些函数并将该 return 值设置为一个变量。然后,检查变量并设置响应对象。对于成功案例,它运行良好,找到了一个东西并设置了响应。问题是,在 SQLITE3 中我很难检查错误。我对数据库服务中的未定义进行了基本检查,如果遇到错误,它会抛出错误,但该错误会立即进入控制器的 CATCH 部分,并且不允许我将其包装在 API 中我想定义的响应。这些是单独的文件(控制器与服务)。我没有找到很多关于 sqlite3 错误检查的有用信息,那里很少。理想情况下,该服务会抛出一个错误,然后我可以将其包装到一个标准化的响应对象中并发送。

------ 地点

const getById = async (req, res, next) => {
    response = {};
    try {
        let location = await getLocationById(req.params.id); // <-- IF NO VALUE FOUND, location IS nothing
        if (error) { // <----- THIS IS WHERE I'D LIKE TO CHECK FOR ERRORS.
            response.status = 404;
            response.message = 'Error attempting to get location';
        } else {
            response.status = 200;
            response.message = 'Success';
            response.data = location;
        }
        res.json(response);
    } catch (error) {
        res.json(response);
    }
};

------------ 服务

const getLocationById = (id) => {
    return new Promise((resolve, reject) => {
        let sql = 'SELECT * FROM Locations WHERE id = ?;';
        db.get(sql, [id], (error, location) => {
            if (location !== undefined) {
                resolve(location);
            } else {
                reject(new Error('Error attempting to get location by id'));
            }
        });
    });
};

您只需将对 getLocationById() 的调用包装在另一个 try/catch 中。从那里您可以决定是要包装还是引发错误。如果您没有要添加的其他代码可能会引发错误,您可以删除外部 try/catch。在线评论中的更多解释和建议:

const getLocationById = (id) => {
  return new Promise((resolve, reject) => {
    const sql = "SELECT * FROM Locations WHERE id = ?;";
    db.get(sql, [id], (error, location) => {
      // check for an error from the db here
      if (error) return reject(error);
      // check for an empty result here and throw your own error
      if (!location) {
        // set a property so we can tell that it wasn't a db error just not found
        const myError = new Error("Error attempting to get location by id");
        myError.notFound = true;
        return reject(myError);
      }
      // otherwise resolve the result
      return resolve(location);
    });
  });
};
const getById = async (req, res, next) => {
  // use const since it is not reassigned, only properties are changed
  const response = {};
  try {
    // code here that might throw an exception
    try {
      // use const if you aren't going to reassign `location`
      const location = await getLocationById(req.params.id); 
      
      // we were able to load the location if we get here
      response.status = 200;
      response.message = "Success";
      response.data = location;
    } catch (error) {
      // maybe check to see if we want to wrap or raise the error
      // maybe call console.log(error) to see the contents
      const doWeWantToWrapTheError = somethingToCheckTypeEtc(error);
      if (doWeWantToWrapTheError) {
        if (error.notFound) {
          // no db errors, just not found
          response.status = 404;
        } else {
          // some kind of db error so set to "internal server error"
          response.status = 500;
        }
        response.message = "Error attempting to get location";
      } else {
        // raise the error to the outer try/catch
        throw error;
      }
    }
    // code here that might throw an exception
    return res.json(response);
  } catch (unexpected) {
    // some other error occurred that was not caught above (unlikely)
    // maybe call console.log(unexpected) to see the contents
    response.error = unexpected.message;
    return res.json(response);
  }
};