哪些场景下使用await/async更好?哪些场景下使用then更好?

哪些场景下使用await/async更好?哪些场景下使用then更好?

我的认为await/async的出现是为了改善then的使用,当比较复杂的时候,await/async会起到作用,当问题比较简单的时候用then。但是我们还是应该选择其中一种,这样代码风格比较统一。

例如我下面这个需求使用的await/async不知道是否合适(是不是变得麻烦了?)
工作1:获得选择列表,并默认选择全部。
工作2:根据选择的单位和其他信息向服务端发送请求,获取数据之后根据数据刷新页面

当初始加载该页面的时候,整合工作1和工作2。

async function getDwSelections() {
  try {
    const result = await getDwList();
    if (!result.isSucceed) throw new Error("获取单位列表失败,错误信息:' + result.errMsg")
    const data = result.data[0].datas
    console.log("dw selections: ", data);
    dwSelections.value.push({
      value: "全部",
      label: "全部"
    })
    for (const item of data) {
      dwSelections.value.push({
        value: item.dwdm,
        label: item.dwmc
      })
    }
    selectedDw.value = "全部";
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : error;
    throw new Error(errorMessage);
  }
}
async function query() {
  try {
    const result = await getTableData({dwdm: selectedDw.value === "全部" ? '' : selectedDw.value, ny: selectedDate.value})
    if (!result.isSucceed) throw new Error("获取数据失败,错误信息:" + result.errMsg)
    rqToDm.value = {};
    const data = result.data[0].datas;
    const newTableData = new Map();
    const newDateFields = new Set();
    const currentDate = common.getCurrentDate("yyyy-MM-dd");
    for (const entry of data) {
     if(entry.rqdm > currentDate) continue;
      if (newTableData.has(entry.jlid)) {
        newTableData.get(entry.jlid)[entry.rq] = entry.rjql;
      } else {
        newTableData.set(entry.jlid, {
          jlid: entry.jlid,
          ny: selectedDate.value,
          dwmc: entry.dwmc,
          jqd: entry.jqd,
          dlgs: entry.dlgs,
          jqfs: entry.jqfs,
          ljjql: entry.ljjql,
          rpjql: entry.rpjql,
          ljdsl: entry.ljdsl,
          [entry.rq]: entry.rjql
        })
      }
      newDateFields.add(entry.rq)
      rqToDm.value[entry.rq] = entry.rqdm;
    }
    dateFields.value = Array.from(newDateFields).map(e => {
      return {"label": e, "prop": e};
    });
    tableData.value = Array.from(newTableData.values());

  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : error;
    throw new Error(errorMessage);
  }
}
onMounted(async () => {
  loading.value = true;
  try {
    await getDwSelections();
    await query()
  } catch (error) {
    ElMessage.error(error.message);
  }
  loading.value = false;
})

附:代码中有什么其他问题也欢迎指正。

阅读 786
avatarAI BotBETA

使用await/async的场景

  • 当需要按照顺序执行多个异步操作时,await/async 提供了更清晰的控制流,使得代码看起来像同步代码一样,易于理解和维护。
  • 在需要等待异步操作结果,并且基于该结果执行后续操作时,await/async 是很好的选择。
  • 当需要在异步函数中使用try...catch来捕获错误时,await/async 是唯一的选择,因为then的链式调用中捕获错误通常需要使用额外的.catch()方法。
  • 在处理嵌套异步调用时,await/async 可以避免回调地狱(Callback Hell),使得代码更加简洁和可读。

在你的例子中,使用await/async是合适的,因为你需要按顺序执行getDwSelectionsquery函数,并且基于这些函数的结果来更新页面。

使用then的场景

  • 当不需要等待异步操作的结果,或者不需要基于该结果执行后续操作时,可以使用.then()
  • 在某些老旧的代码库或特定的编程风格中,可能更倾向于使用.then()来处理异步操作。
  • 当需要并行执行多个异步操作,并且不关心它们的完成顺序时,可以使用Promise.all().then()结合来同时处理所有操作的结果。

你的代码中的问题

你的代码在逻辑上是清晰的,使用了await/async来按顺序执行异步操作,并使用了try...catch来捕获错误。不过,有一些小的改进点:

  1. 错误处理:在catch块中,你重新抛出了一个错误。虽然这没有问题,但如果你只是想记录错误而不希望中断程序流程(比如,在开发环境中),你可能只是想要打印或记录错误,而不是重新抛出它。
  2. 错误消息:在throw new Error中,字符串拼接有误。你使用了单引号包围了字符串字面量,但忘记了在+操作符之后添加单引号来继续字符串字面量。应该修改为:

    throw new Error("获取单位列表失败,错误信息:" + result.errMsg);
  3. 代码复用:在query函数中,错误处理部分与getDwSelections中的类似。如果这种错误处理逻辑在多个地方都有使用,可以考虑将其封装为一个单独的函数或方法。
  4. 状态管理:你的代码中使用了多个全局变量(如dwSelections.valueselectedDw.value等)来管理状态。虽然这在Vue这样的框架中是常见的,但确保这些变量在组件的适当范围内被正确初始化和管理是很重要的。
  5. 代码组织:考虑将getDwSelectionsquery函数组织到一个更具体的模块或服务中,以便在其他地方重用这些逻辑。
  6. 代码可读性:函数和变量名应该清晰明了,反映它们的用途。例如,rqToDm.valuedateFields.value这样的变量名可能需要一些上下文才能理解其含义。如果可能的话,使用更具描述性的名称可以提高代码的可读性。
1 个回答
  1. 顺序执行,后面的环节依赖前面的结果,用 await
  2. 支线执行,不影响主线,用 .then,比如数据埋点
  3. 需要跨文件等待执行结束,return new Promise
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏