代码之家  ›  专栏  ›  技术社区  ›  Siya Mzam

代码可以工作,但在promise中有一个try/catch块是最佳实践吗?

  •  1
  • Siya Mzam  · 技术社区  · 6 年前

    try/catch 用一个 Promise ? 我在复习下面的代码,我似乎无法理解使用 尝试/抓住 许诺 . 还有,为什么没有地方 许诺 拒绝,正如您在 catch 块,该 许诺 解决。请帮助我理解这段代码,从最佳实践和效率的角度来看 尝试/抓住 内部 许诺

    我也非常感谢任何关于清理冗余代码的建议。

    getRoute(): any {
        return async (request: any, reply: any) => {
          const result = new Promise<string>( async (resolve, reject) => {
            try {
              let userIsValid = await this.validator.validate(request.payload, RegisterUserValidator);
              if (userIsValid.error) {
                resolve(responseHelper.getErrorResponse(ResponseErrorCode.joiValidatorError, userIsValid.error));
                throw new ControlFlowNonError();
              }
              let results = await this.authUser.registerUser(request.payload);
              resolve(responseHelper.getSuccessResponse(results, null));
            }
            catch (error) {
              let message: ILogMessage = {
                code: ResponseErrorCode.unknownError,
                message: ResponseErrorCode.unknownError.toString(),
                meta: error,
                sourceFunction : 'ApiDataCreateCredentials: getRoute()'
              };
              this.logHelper.error(message);
              resolve(error);
            }
          });
          reply(result);
        };
      };
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   jfriend00    6 年前

    在promise[executor函数]内设置try/catch块是最佳做法吗?

    不,这不是最佳做法。在承诺执行器函数中几乎没有理由使用承诺。因为当你这样做的时候,你根本不需要外部的、手动创建的承诺。你可以回报内心的承诺。这就是 Promise constructor anti-pattern .

    仅供参考,虽然这不是你的情况,但使用它是合理的 try/catch 处理承诺执行器内部的常规异常(如果首先实际需要手动创建的承诺执行器,并且需要关注常规异常,并且您希望在本地处理它们)。


    这里有另一个关于如何实现相同逻辑的想法。这将删除 promise anti-pattern 用另一个手动创建的承诺包围一个承诺,并使用承诺流控制来 userIsValid.error 转到日志错误代码。我没有看到在这里使用wait有什么特别的优势,所以我改回只使用wait .then() .catch() . 我不知道TypeScript,所以这是代码的常规Javascript版本,但您可以自己添加一些语法差异,将其转换回TypeScript:

    getRoute(): function() {
        return function(request, reply) {
            return this.validator.validate(request.payload, RegisterUserValidator).then(userIsValid => {
                if (userIsValid.error) {
                    // treat this as an error condition
                    throw responseHelper.getErrorResponse(ResponseErrorCode.joiValidatorError, userIsValid.error);
                }
                return this.authUser.registerUser(request.payload).then(results => responseHelper.getSuccessResponse(results, null));
            }).catch(error => {
              let message: ILogMessage = {
                code: ResponseErrorCode.unknownError,
                message: ResponseErrorCode.unknownError.toString(),
                meta: error,
                sourceFunction : 'ApiDataCreateCredentials: getRoute()'
              };
              this.logHelper.error(message);
              // turn back into resolved promise with error as the result
              return error;
            }).then(reply);        // always call reply
        }
    }    
    

    在您的实现中似乎并不理想的事情:

    1. Promise anti-pattern (创建不必要的包装承诺)。
    2. 使命感 resolve() 多次(第二次将被忽略,但这样编码似乎不太理想)
    3. 使用似乎没有任何特别的好处 async/await
    4. 解析() 然后 throw 在阅读代码时真是让人头疼。是的,人们最终可以知道你在做什么,但这是一种奇怪的方式。我的方案更具语义。 if (userIsValid.error) 这对你来说只是一个错误条件,所以用这种方式编码只会让它变得更明显。然后,由于您希望所有错误都像没有错误一样继续(在记录之后),我们只需 .catch() 处理程序正常返回,允许最后一个 .然后() 处理程序总是被调用。

    Can't throw error from within an async promise executor function

    Is it an anti-pattern to use async/await inside of a new Promise() constructor?