代码有效,但最好的做法是在promise中包含try / catch块吗?

时间:2017-11-04 16:10:21

标签: javascript node.js promise try-catch typescript2.0

try/catchPromise打包在一起是不错的做法?我正在审核下面的代码,我似乎无法理解在try/catch中有Promise块的必要性。另外,为什么没有Promise拒绝的地方,正如您在catch块中看到的那样Promise结算。请帮助我理解这段代码,在最佳实践和效率方面,try/catch内部Promise。{/ p>

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

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 个答案:

答案 0 :(得分:2)

  

最好在promise [executor function]中包含try / catch块吗?

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

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

这是另一个如何实现相同逻辑的想法。这将删除围绕承诺的promise anti-pattern与另一个手动创建的承诺,并使用承诺流控制使userIsValid.error转到日志错误代码。我没有看到在这里使用等待的任何特殊优势,所以我切换回使用.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. 在阅读代码时,
  5. resolve()后跟throw是一个真正的头脑。是的,人们最终可以弄清楚你正在尝试做什么,但这是一个奇怪的方法。我的方案更具语义性。 if (userIsValid.error)对你来说真的只是一个错误条件,所以这样编码只会让它变得更加明显。然后,由于您希望所有错误继续进行,就好像没有错误(在记录之后),我们只是使.catch()处理程序正常返回,这允许始终调用最后一个.then()处理程序。
  6. 与您的主题相关的其他参考:

    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?