代码有效,但是在承诺中使用 try/catch 块是最佳实践吗?
Code works, but is it best practice to have a try/catch block inside a promise?
用 Promise
包裹 try/catch
是好习惯吗?我正在查看下面的代码,我似乎无法理解 Promise
中有一个 try/catch
块的必要性。另外,为什么没有 Promise
拒绝的地方,正如您在 catch
块中看到的那样,Promise
解析。请帮助我理解这段代码,就最佳实践和效率而言,在 Promise
.
中包含 try/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);
};
};
Is it best practice to have a try/catch block inside a promise [executor function]?
不,这不是最佳做法。几乎没有理由在 promise 执行器函数中使用 promises。因为当你这样做时,你根本不需要外部的、手动创建的承诺。你可以 return 内心的承诺。那就是 Promise constructor anti-pattern.
仅供参考,虽然这不是你的情况,但使用 try/catch
处理 promise 执行器中的常规异常是合理的(如果首先实际需要手动创建的 promise 执行器,并且如果经常出现的异常令人担忧,您想在本地处理它们。
这是关于如何实现相同逻辑的另一个想法。这消除了 promise anti-pattern 用另一个手动创建的承诺包围一个承诺,并使用承诺流控制使 userIsValid.error
转到日志错误代码。我没有看到在这里使用 await 有什么特别的优势,所以我切换回只使用 .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
}
}
您的实施似乎不太理想的地方:
- Promise anti-pattern(创建一个不必要的包装承诺)。
- 多次调用
resolve()
(第二个将被忽略,但这样编码似乎不太理想)
- 这里使用
async/await
似乎没有什么特别的好处。这似乎使流程复杂化(在我看来)。
resolve()
后跟 throw
是阅读代码时真正令人头疼的问题。是的,人们最终可以弄清楚您要做什么,但这是一种奇怪的方法。我的方案更具语义性。 if (userIsValid.error)
对您来说实际上只是一个错误条件,因此以这种方式编码只会使它更加明显。然后,由于您希望所有错误都像没有错误一样继续进行(在记录之后),我们只需正常地使 .catch()
处理程序 return 允许最后一个 .then()
处理程序始终被调用.
与您的主题相关的其他参考资料:
用 Promise
包裹 try/catch
是好习惯吗?我正在查看下面的代码,我似乎无法理解 Promise
中有一个 try/catch
块的必要性。另外,为什么没有 Promise
拒绝的地方,正如您在 catch
块中看到的那样,Promise
解析。请帮助我理解这段代码,就最佳实践和效率而言,在 Promise
.
try/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);
};
};
Is it best practice to have a try/catch block inside a promise [executor function]?
不,这不是最佳做法。几乎没有理由在 promise 执行器函数中使用 promises。因为当你这样做时,你根本不需要外部的、手动创建的承诺。你可以 return 内心的承诺。那就是 Promise constructor anti-pattern.
仅供参考,虽然这不是你的情况,但使用 try/catch
处理 promise 执行器中的常规异常是合理的(如果首先实际需要手动创建的 promise 执行器,并且如果经常出现的异常令人担忧,您想在本地处理它们。
这是关于如何实现相同逻辑的另一个想法。这消除了 promise anti-pattern 用另一个手动创建的承诺包围一个承诺,并使用承诺流控制使 userIsValid.error
转到日志错误代码。我没有看到在这里使用 await 有什么特别的优势,所以我切换回只使用 .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
}
}
您的实施似乎不太理想的地方:
- Promise anti-pattern(创建一个不必要的包装承诺)。
- 多次调用
resolve()
(第二个将被忽略,但这样编码似乎不太理想) - 这里使用
async/await
似乎没有什么特别的好处。这似乎使流程复杂化(在我看来)。 resolve()
后跟throw
是阅读代码时真正令人头疼的问题。是的,人们最终可以弄清楚您要做什么,但这是一种奇怪的方法。我的方案更具语义性。if (userIsValid.error)
对您来说实际上只是一个错误条件,因此以这种方式编码只会使它更加明显。然后,由于您希望所有错误都像没有错误一样继续进行(在记录之后),我们只需正常地使.catch()
处理程序 return 允许最后一个.then()
处理程序始终被调用.
与您的主题相关的其他参考资料: