如何在 Nuxt 的 asyncData 中对 Promise.all 进行数组解构

Posted

技术标签:

【中文标题】如何在 Nuxt 的 asyncData 中对 Promise.all 进行数组解构【英文标题】:How to array destructure a Promise.all in Nuxt's asyncData 【发布时间】:2021-07-26 09:04:04 【问题描述】:

我正在使用 Nuxt 和 Vue,以及 mysql 数据库,所有这些对我来说都是新的。我正在从 WebMatrix 过渡出来,在那里我有一个用于多个表的管理页面,并带有用于选择特定选项的下拉菜单。在这个页面上,我可以选择添加、编辑或删除选定的选项,比如作曲家或音乐作品。以下是其中 2 个表的一些代码(出现模块构建失败的运行时错误):

<script> 
export default 
  async asyncData(context) 
    let [arrangers, composers] = await Promise.all([
      context.$axios.get(`/api/arrangers`),
      context.$axios.get(`/api/composers`),
    ])
    const arrangers = await context.$axios.get('/api/arrangers')
    const composers = await context.$axios.get('/api/composers')  

    return  arrangers, composers  
  ,

</script>

【问题讨论】:

您好,您一次只能问一个问题。对于“如何在单个页面上执行多个 asyncData 请求”,到目前为止,您的代码在这里工作得还好吗? (asyncData) 不,我收到运行时错误。我看到我已经定义了两次编曲者和作曲家。但是,如果我取出任何一个定义(let 或 const),我不会收到运行时错误,但也不会收到任何数据。 另外,您来自I also have the problem of getting...的部分问题应该被删除。尝试每个问题帖子只问一件事。如果你想问第二部分,只需创建一个新帖子。否则,您可能会看到您的问题因Needs more focus 原因(This question currently includes multiple questions in one. It should focus on one problem only)而关闭。 我已经编辑了您最初的问题,使其仅限于一件事。随意将第二部分发布到另一个帖子中! 【参考方案1】:

对于输入(Promise.all 的左侧部分)和 axios 调用的结果,您确实具有相同的变量名称,为避免命名冲突,您可以重命名结果并返回:

const  arrangers: fetchedArrangers  = await context.$axios.get('/api/arrangers')
const  composers: fetchedComposers  = await context.$axios.get('/api/composers')

return  fetchedArrangers, fetchedComposers  

编辑,我就是这样写的

async asyncData( $axios ) 
  const [posts, comments] = await Promise.all([
    $axios.$get('https://jsonplaceholder.typicode.com/posts'),
    $axios.$get('https://jsonplaceholder.typicode.com/comments'),
  ])
  console.log('posts', posts)
  console.log('comments', comments)

  return  posts, comments 
,

当您在 Promise.all 的结果末尾进行解构时,您需要根据从 API 获得的结果进行解构。通常,您确实有data,所以 arrangers composers 通常不起作用。当然,这取决于您自己的 API 以及是否返回这种类型的数据。

由于解构 2 data 是不可行的,所以最好简单地使用数组解构。这样,它会返回包含 data 数组的对象。

要直接访问数据,您可以使用$get shortcut,这在我们的例子中很方便。直接解构$axios 也不错,会去掉可有可无的context

在我的示例中,我使用 JSONplaceholder 来实现经典的 API 行为(尤其是 data 部分),但它可以像这样与任何 API 一起使用。

这是最终结果。

此外,如果您仅使用 this.$axios.get,就会发生这种情况:您将拥有著名的 data,稍后您将需要访问 (.data) 以仅使用有用的部分API 的响应。这就是我喜欢 $get 快捷方式的原因,它可以更快地切入主题。


PS:所有这些都是可能的,因为Promise.all 保留了调用顺序:https://***.com/a/28066851/8816585


EDIT2:如何使其更灵活的示例可能是

async asyncData( $axios ) 
  const urlEndpointsToFetchFrom = ['comments', 'photos', 'albums', 'todos', 'posts']
  const allResponses = await Promise.all(
    urlEndpointsToFetchFrom.map((url) => $axios.$get(`https://jsonplaceholder.typicode.com/$url`)),
  )

  const [comments, photos, albums, todos, posts] = allResponses
  return  comments, photos, albums, todos, posts 
,

当然,保持数组解构的顺序很重要。它可能以动态方式可行,但我不知道如何。

另外,我不能推荐足够的东西来尝试fetch() 钩子替代方案。我发现它更灵活,而且它确实有一个很好的 $fetchState.pending 助手,更多信息在这里:https://nuxtjs.org/blog/understanding-how-fetch-works-in-nuxt-2-12/ 和页面底部的文章中。

【讨论】:

感谢您的回复。我试过了: const data1:arrangers = await context.$axios.get('/api/arrangers') const data2: composers = await context.$axios.get('/api/composers') console.log (arrangers, composers) return arrangers, composers 编曲者和作曲家都返回 undefined。 嗯等等,我之前没有注意到,但你为什么在之后使用Promise.all$axios.get?你应该只有两者之一。最重要的是,您需要将重命名的变量名称放在右侧而不是左侧,因此 data1 在这种情况下是 API 返回给您的内容,因此可能不是这样。 API 是否公开供我试用?或者你能分享一些网络负载吗? 感谢您的深入回复!!!这适用于我的 2 个入门请求。现在添加其他 7 个请求。我意识到我有很多东西要学。我确实注意到了 Promise 和 $axios.get 的重复,但单独删除其中任何一个都没有任何区别。您的代码有效。

以上是关于如何在 Nuxt 的 asyncData 中对 Promise.all 进行数组解构的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Nuxt 访问 asyncData 中的数据

如何测试 nuxt.js asyncData 并获取钩子

如何使用 Nuxt 和 asyncData 观察路由变化

在 Nuxt 中硬刷新时的 asyncData 钩子

“默认 Apollo 查询”VS “AsyncData”(Nuxt.js)

nuxt.js中asyncData 方法能够在渲染组件之前异步获取数据