vueuse 使用案例 - computedAsync

1,755 阅读2分钟

作者:陈云杰

vue3 引入的 composition api 确实是一个质的飞跃,他完美的决绝了 vue 组件之间共享代码的问题,感谢 react 🤪

vueuse 是一套基于 composition api的函数库,可以理解成 vue 的 lodash,但是有时候很难知道哪些问题是vueuse里已经有解决方案了的,所以我想写一个系列,把平时用到的效果很好的 vueuse 方法记录下来。

今天我们就来看一下 computedAsync

image.png

假设有一个这样的场景,用户可以在日历控件中点击不同的日期来查询当天的待办,想象一下该怎么实现这个需求:

const selectedDate = ref(new Date());   //用户选中的日期

我应该 watch selectedDate 这个变量,当他变化的时候通过api请求来拉取数据

watch(selectedDate, ()=>fetchTodos(...))

这样用户每点击一个日期,我们就会获取这个日期的待办数据。

我们已经实现了这个功能,但是不完美,想象一下如果用户非常快速的点击不同的日期(1,2,3,4日)会发生什么情况?

  • 1号的数据可能会在切换到4号后才请求完毕,并显示在4号的列表里(请求先发先至),当然这个问题可以用其他方法解决
  • 产生大量的 pending 请求,4号的数据要等前面的请求都结束才能正常返回(在弱网和http1下问题更严重)

所以需要一个方法来cancel掉旧的api请求,当我点击到4号的时候取消掉之前还没有结束的请求来节省资源。

vueuse 中的 computedAsync 完美的解决了这个问题

  const todoList = computedAsync(
    async onCancel => {
      const abortController = new AbortController();

      onCancel(() => abortController.abort());

      const data = await fetchTodos(
        selectedDate,
        abortController.signal
      );
      return data;
    },
    []
  );

看名称就能知道他和 vue 内置的 computed 很像,只不过是一个异步的版本。 computedAsync在执行传入的callback时调用了selectedDate变量,selectedDate就会被收集成为一个依赖,当selectedDate变化的时候,callback就会被重新调用。

到目前为止他和 computed 还是一模一样的, 那么他和 computed 有哪些区别呢?

  • computedAsynccallback可以是异步的,例如发送http请求。
  • computedAsynccallback有一个onCancel参数,用来取消之前还没有结束的异步callback。

我们来看一下效果,为了模拟弱网场景,我在devtool里设置了 低速3g

20220819150858.gif

从动画里能看到当我点击一个新的日期时旧的请求就会被 cancel 掉,完美解决了问题 🎉

参考: vueuse.org/core/comput…