嵌套 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 中或在其他级别声明后立即聚合取决于您要实现的特定功能。

问问自己:

  1. performActions 函数作为单个 "operation" 是否有意义?如果你能轻松命名它 - 绝对是这样。
  2. performActions是否与apiconsumer中的其他函数相关?看起来它更抽象,所以也许有一些中间层 "between" 你可以把它放在这两个地方,比如 "service" 或 "controller"?我猜你将 apiconsumer 设计成只是端点和基本调用的列表,最好不要用更复杂的函数污染它。
  3. 错误(拒绝)会被事件监听器捕获吗?如果是这样,是否可以将所有 3 个异常合并到一个处理程序中?

总的来说,我总是可以将我的应用程序分成 "sorta MVC" 层:

  1. 查看,即显示 - 您的组件和 DOM 操作
  2. 模型 - api 调用 - 尽可能愚蠢;加上一些不可避免的数据格式化逻辑
  3. 控制器 - 其他一切,你需要计算的东西,你需要同步的调用等等。

这只是基本思路,您可以根据需要对其进行调整和使用。

您还可以使用一些现成的架构,例如 redux、mobx 等。如果您不想受困于这些 "frameworks",您至少可以从如何构造事物。