嵌套 async/await 是反模式吗?
Is it an anti-pattern to nest async/await?
我有 getAction1、2 和 3 函数在后端 API 服务中执行一些操作。
我需要一个按顺序执行 getAction1、2 和 3 的按钮。
在这种情况下,
这样做更好吗? (选项 1)
apiconsumer.js
export const getAction1 = (param1) => new Promise(
function (resolve, reject) {
// DO SOMETHING AND RETURN 'resolve' or 'reject'
});
export const getAction2 = (param2) => new Promise(
function (resolve, reject) {
// DO SOMETHING AND RETURN 'resolve' or 'reject'
});
export const getAction3 = (param3) => new Promise(
function (resolve, reject) {
// DO SOMETHING AND RETURN 'resolve' or 'reject'
});
button.js
const handleOnClick = async (event) => {
const response1 = await getAction1(param1);
const response2 = await getAction2(param2);
const response3 = await getAction3(param3);
// DO SOMETHING...
};
或者这样做? (选项 2)
apiconsumer.js
export const getAction1 = (param1) => new Promise(
function (resolve, reject) {
// DO SOMETHING AND RETURN 'resolve' or 'reject'
});
export const getAction2 = (param2) => new Promise(
function (resolve, reject) {
// DO SOMETHING AND RETURN 'resolve' or 'reject'
});
export const getAction3 = (param3) => new Promise(
function (resolve, reject) {
// DO SOMETHING AND RETURN 'resolve' or 'reject'
});
export const performActions = async (uData) => {
const response1 = await getAction1(uData.param1);
const response2 = await getAction2(uData.param2);
const response3 = await getAction3(uData.param3);
};
button.js
const handleOnClick = async (event) => {
const response1 = await performActions(uData);
// DO SOMETHING...
};
基本上,OPTION.2 创建一个嵌套的 async/await 函数。
我不确定像上面的 OPTION.2 那样嵌套 async/await 是否是个好主意。如果 none 这些都不错,你有什么建议?
全部使用 Promise
如果结果互不依赖
await Promise.all([
getAction1(uData.param1),
getAction2(uData.param2);,
getAction3(uData.param3);
])
对我来说,从 "view" 中抽象出尽可能多的业务逻辑是很明显的。在这种情况下,您的按钮似乎是 "view"。动作 1、2、3 是否异步并不重要,对我来说它们属于处理业务逻辑的某个层,而不是显示。
"nest"(或者 "aggregate")async/await
是否优雅并不是问题,因为你确实可以。大多数复杂的前端 API 都是这样工作的,你绝对应该这样做。
但是,它们是否应该在 apiconsumer
中或在其他级别声明后立即聚合取决于您要实现的特定功能。
问问自己:
performActions
函数作为单个 "operation" 是否有意义?如果你能轻松命名它 - 绝对是这样。
performActions
是否与apiconsumer
中的其他函数相关?看起来它更抽象,所以也许有一些中间层 "between" 你可以把它放在这两个地方,比如 "service" 或 "controller"?我猜你将 apiconsumer
设计成只是端点和基本调用的列表,最好不要用更复杂的函数污染它。
- 错误(拒绝)会被事件监听器捕获吗?如果是这样,是否可以将所有 3 个异常合并到一个处理程序中?
总的来说,我总是可以将我的应用程序分成 "sorta MVC" 层:
- 查看,即显示 - 您的组件和 DOM 操作
- 模型 - api 调用 - 尽可能愚蠢;加上一些不可避免的数据格式化逻辑
- 控制器 - 其他一切,你需要计算的东西,你需要同步的调用等等。
这只是基本思路,您可以根据需要对其进行调整和使用。
您还可以使用一些现成的架构,例如 redux、mobx 等。如果您不想受困于这些 "frameworks",您至少可以从如何构造事物。
我有 getAction1、2 和 3 函数在后端 API 服务中执行一些操作。
我需要一个按顺序执行 getAction1、2 和 3 的按钮。
在这种情况下,
这样做更好吗? (选项 1)
apiconsumer.js
export const getAction1 = (param1) => new Promise(
function (resolve, reject) {
// DO SOMETHING AND RETURN 'resolve' or 'reject'
});
export const getAction2 = (param2) => new Promise(
function (resolve, reject) {
// DO SOMETHING AND RETURN 'resolve' or 'reject'
});
export const getAction3 = (param3) => new Promise(
function (resolve, reject) {
// DO SOMETHING AND RETURN 'resolve' or 'reject'
});
button.js
const handleOnClick = async (event) => {
const response1 = await getAction1(param1);
const response2 = await getAction2(param2);
const response3 = await getAction3(param3);
// DO SOMETHING...
};
或者这样做? (选项 2)
apiconsumer.js
export const getAction1 = (param1) => new Promise(
function (resolve, reject) {
// DO SOMETHING AND RETURN 'resolve' or 'reject'
});
export const getAction2 = (param2) => new Promise(
function (resolve, reject) {
// DO SOMETHING AND RETURN 'resolve' or 'reject'
});
export const getAction3 = (param3) => new Promise(
function (resolve, reject) {
// DO SOMETHING AND RETURN 'resolve' or 'reject'
});
export const performActions = async (uData) => {
const response1 = await getAction1(uData.param1);
const response2 = await getAction2(uData.param2);
const response3 = await getAction3(uData.param3);
};
button.js
const handleOnClick = async (event) => {
const response1 = await performActions(uData);
// DO SOMETHING...
};
基本上,OPTION.2 创建一个嵌套的 async/await 函数。
我不确定像上面的 OPTION.2 那样嵌套 async/await 是否是个好主意。如果 none 这些都不错,你有什么建议?
全部使用 Promise
如果结果互不依赖
await Promise.all([
getAction1(uData.param1),
getAction2(uData.param2);,
getAction3(uData.param3);
])
对我来说,从 "view" 中抽象出尽可能多的业务逻辑是很明显的。在这种情况下,您的按钮似乎是 "view"。动作 1、2、3 是否异步并不重要,对我来说它们属于处理业务逻辑的某个层,而不是显示。
"nest"(或者 "aggregate")async/await
是否优雅并不是问题,因为你确实可以。大多数复杂的前端 API 都是这样工作的,你绝对应该这样做。
但是,它们是否应该在 apiconsumer
中或在其他级别声明后立即聚合取决于您要实现的特定功能。
问问自己:
performActions
函数作为单个 "operation" 是否有意义?如果你能轻松命名它 - 绝对是这样。performActions
是否与apiconsumer
中的其他函数相关?看起来它更抽象,所以也许有一些中间层 "between" 你可以把它放在这两个地方,比如 "service" 或 "controller"?我猜你将apiconsumer
设计成只是端点和基本调用的列表,最好不要用更复杂的函数污染它。- 错误(拒绝)会被事件监听器捕获吗?如果是这样,是否可以将所有 3 个异常合并到一个处理程序中?
总的来说,我总是可以将我的应用程序分成 "sorta MVC" 层:
- 查看,即显示 - 您的组件和 DOM 操作
- 模型 - api 调用 - 尽可能愚蠢;加上一些不可避免的数据格式化逻辑
- 控制器 - 其他一切,你需要计算的东西,你需要同步的调用等等。
这只是基本思路,您可以根据需要对其进行调整和使用。
您还可以使用一些现成的架构,例如 redux、mobx 等。如果您不想受困于这些 "frameworks",您至少可以从如何构造事物。