gpt4 book ai didi

javascript - Javascript:在请求的对象“未找到”的情况下,使用模式空对象模式,RORO,未定义等作为Get函数的返回参数

转载 作者:行者123 更新时间:2023-11-29 10:58:27 25 4
gpt4 key购买 nike

首先,我不确定该主题是否属于StackOverflow。但是,我发现了有关其他编程语言的一些讨论,这些讨论解决了StackOverflow上的主题,但不适用于Javascript。因此,我将把问题抛诸脑后:

在Javascript中假设的GetUserByUsername函数中,处理可能的“未找到”方案的最佳方法/模式是什么。

我为什么要问?我想在整个项目中遵循某种编码标准。

我的更具体的情况如下:

  • 我有上级用户
  • 我有一个包含以下实例的用户列表
    类用户
  • 我正在寻找某个用户,但该用户没有
    存在于列表


  • 我应该如何处理有关职能的“找不到”情况?

    我发现以下方法:
  • 返回未定义的
  • RORO(接收对象,返回对象)
  • 空对象模式
  • 引发自定义错误

  • 那我到底是什么意思。以下面的示例类User为例。
    module.exports = class User {
    constructor() {
    this.userName = null,
    this.name = null,
    this.age = null
    }
    ...
    getName() {
    console.log(this.name);
    }
    }

    在我的代码中的某个地方,我有一个函数,该函数提供了根据用户列表中的用户名返回某个用户的功能。该列表是一个数组,其中包含User类的实例。

    一个简单的实现可能是这样的:
    {
    ...

    getUserByUsername(pUserName) {
    /* listOfUsers array with objects of the class User */
    var lUser = this.listOfUsers.find(user => user.userName === pUserName);
    return lUser;
    }
    ...
    }

    在某些情况下,传递的用户名可能不属于某个用户。因此,找不到用户。

    我该如何处理?

    1.)返回未定义-就像示例代码一样。
    /* We expect "Unknown" is not a user name in that list*/
    var lRequestedUser = getUserByUsername("Unknown");

    /* Check if requested user is undefined. Note: I'm using lodash for staff like that */
    if(_.undefined(lRequestedUser)) {
    //Handling
    }

    lRequestedUser.getName();

    2.)RORO(接收对象,返回对象)
    我将一个对象传递给函数,并返回一个对象作为结果。在我要返回的对象中,我有一个指示器,指示操作是否成功。
    getUserByUsername(pParams) {
    if(_.undefined(pParams.userName)) {
    //Throw custom error
    }

    var lReturnObject = {
    isSuccessfull: false,
    data: null
    }

    /* listOfUsers array with objects of the class User */
    var lUser = this.listOfUsers.find(user => user.userName === pParams.userName);

    if(!(_.undefined(lUser))) {
    lReturnObject.isSuccessfull = true;
    lReturnObject.data = lUser
    }
    return lUser;
    }
    ...
    }

    /*
    Building a object which is passed to the function. Username is a member of that object
    */
    var lRequest = {
    userName: "Unknown"
    }

    /* We expect "Unknown" is not a user name in that list*/
    var lRequestedUser = getUserByUsername(lRequest);

    if(!(lRequestedUser.isSuccessfull)) {
    //Handling
    }

    lRequestedUser.data.getName();

    3.)空对象模式
    我不喜欢这种解决方案的事实是,如果主类获得了附加功能,我总是必须为空对象增强类。
      module.exports = class NullUser {
    constructor() {
    this.userName = null,
    this.name = null,
    this.age = null
    }
    ...
    getName() {
    console.log(this.name);
    }
    }


    {
    ...

    getUserByUsername(pUserName) {
    /* listOfUsers array with objects of the class User */
    var lUser = this.listOfUsers.find(user => user.userName === pUserName);

    if(_.undefined(lUser)) {
    return new NullUser();
    }

    return lUser;
    }
    ...
    }


    /* We expect "Unknown" is not a user name in that list*/
    var lRequestedUser = getUserByUsername("Unknown");
    lRequestedUser.getName();

    4.)引发自定义错误
    {
    ...
    getUserByUsername(pUserName) {
    /* listOfUsers array with objects of the class User */
    var lUser = this.listOfUsers.find(user => user.userName === pUserName);

    if(_.undefined(lUser)) {
    throw new CustomError(...);
    }

    return lUser;
    }
    ...
    }

    /* We expect "Unknown" is not a user name in that list*/
    try {
    var lRequestedUser = getUserByUsername("Unknown");
    lRequestedUser.getName();
    } catch (e) {
    if (e instanceof CustomError) {
    //Handling
    }
    }

    我个人更喜欢返回包含指示符的对象的选项,以及引发自定义错误的选项。该示例是同步的。在我的项目中,我也有异步代码。我为此 promise 。

    因此,有什么想法是“最佳”解决方案或我应该首选的方式?

    最佳答案

    在我看来,答案取决于!
    您提到的所有方法都有特定的用例,每种用例都占主导地位。让我们一个接一个。 (最后是评论家)

    带有回调的异步应用

    尽管回调被认为是陈旧且不费力的,但它们为我们提供了我称之为“多个返回值”的灵活性。

    getUserByName(name, callback) {
    // Caller can check the `err` and `status` to decide what to do next.
    return callback(err, status, user);
    }
  • 在这里,抛出错误将无法按预期进行。也就是说,您无法使用try-catch捕获引发的错误。您当然可以“返回”自定义错误。但这似乎没有意义,能够分别返回“状态”。
  • 使用附加的status参数返回空对象或RORO没有意义。您可能更希望摆脱status,而使用null对象或RORO。


  • 带有Promise / async-await的异步应用程序

    在这里,抛出错误将起作用。如果您使用的是异步等待,则try-catch的catch将得到错误。或者,如果您原样使用Promise,则Promise链的捕获将得到它。

    同步应用程序

    引发错误并使用try-catch可以按预期工作。但是,在使用任何第三方服务的现实世界应用程序中,这种情况很少见。

    但是,毕竟使用异常还是有问题的。是否要将“无数据”方案视为错误取决于业务逻辑。
  • 如果您只想告诉最终用户,则没有此类用户,则可以使用异常。
  • 如果要继续创建新用户,则可能没有意义。您将需要明确地区分错误是由于“无数据”引起的,还是由于“驱动程序错误”,“超时”等引起的。根据我的经验,使用此类异常很容易引入错误。

  • 因此,解决该问题的方法是使用自定义错误。同样,在被 call 者和 call 者中将有太多的样板代码。这甚至可能导致逻辑语义上的困惑。另一方面,自定义错误的使用过多会导致不一致问题,并且随着时间的推移可能导致难以维护的应用程序。 (这完全取决于应用程序的发展方式。例如,如果开发人员经常更换,则不同的人会对这些自定义错误的含义有不同的看法)

    有意见的答案

    看到了良好的应用程序和高度难以维护的整体,我将给您我个人的偏爱。但是请记住,这可能不是最终的解决方案。

    注意:此(建议的)解决方案基于以下事实,
  • 所需的样板代码量
  • 代码
  • 的语义含义
  • 新开发者开始使用
  • 应用程序的便捷性
  • 可维护性

  • 不要使用错误来处理无数据方案。相反,应明确检查“空”数据并分别处理。
    我将在这里使用RORO模式,但有一点不同。我确实返回一个对象,但是接收参数而不是对象。这取决于参数的数量。如果参数数量过多,则接收对象可能是有意义的。但是在我看来,这可能是 表示业务/架构决策不正确的指示

    考虑下面的用户登录示例。
  • 如果登录时发生错误,我会向最终用户显示“错误”状态。
  • 如果成功获取用户,我将用户登录到
  • 如果用户不在,我创建一个新用户。 (假设我从请求中获得了足够的数据,可以这样做)

  • 伪代码可能看起来像这样,
    // Controller code
    async signIn(name, email) {
    try {
    let user = await userDao.getUserByUserName(name);
    if (!user.exists) {
    user = await userDao.createUser(name, email);
    }
    return user;
    } catch(e) {
    // handle error
    }
    }

    或像这样
        // Controller code
    async signIn(name, email) {
    try {
    let result = await userDao.getUserByUserName(name);
    if (!result.user) {
    result = await userDao.createUser(name, email);
    }
    return result.user;
    } catch(e) {
    // handle error
    }
    }

    使用自定义错误的一个好例子是区分错误是在检索用户时还是在创建用户时发生。

    使用 status(作为回调的参数或返回对象的属性)的主要好处是,您可以使用它来将应用程序的其余部分设计为状态机(无数据场景根据用户类型,部分检索等,复杂的业务中可以有很多状态。

    关于javascript - Javascript:在请求的对象“未找到”的情况下,使用模式空对象模式,RORO,未定义等作为Get函数的返回参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52123917/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com