在 Vue.js 中等待 Ajax 响应数据
Posted
技术标签:
【中文标题】在 Vue.js 中等待 Ajax 响应数据【英文标题】:Wait for Ajax response data in Vue.js 【发布时间】:2018-12-21 15:40:42 【问题描述】:我有一个 Vue 组件,我正在尝试使用 axios 从 API 获取一些数据。
<template>
<div>
This is Default child component
tools[0].name
</div>
</template>
<script>
import CustomJS from '../js/custom.js';
export default
name: 'HomeContent',
props:
tools: []
,
methods:
fetchData()
const customJs = new CustomJS();
return customJs.getTools();
,
created()
this.tools = this.fetchData(); //preferably need to wait here wait for response
</script>
getTools()
函数位于 Vue 组件文件之外的另一个 JS 文件中,它使用 axios.get 进行 API 调用。
getTools(id = 0)
this.apiTool += (id > 0) ? id : '';
axios.get(this.apiTool,
)
.then(function (response)
console.log(response.data);
return response.data;
)
.catch(function (error)
console.log(error);
);
问题是,tools
未定义,因为getTools()
需要一些时间才能返回响应数据。怎样才能等待响应数据然后返回?
【问题讨论】:
如果要等待请求完成,可以在getTools()中使用同步http请求 @SagarTamang 不,不是一个好主意。sync
已弃用,请不要建议人们使用随时可能消失的功能。
什么是你需要等待,..你能不能做 -> this.fetchData().then(......
?
@Keith 好的,我会记住的。非常感谢。
我在这里得到了部分解决方案-***.com/questions/43613115/…
【参考方案1】:
我不知道为什么这个问题会出现在我的“时间线”中,并且还没有得到接受的答案,所以无论如何我都会回答。问题似乎在于对 JS 中异步代码的 OP 的理解。这是使它变得更好的修复(有 3 个):
<template>
<div v-if="tools.length">
tools[0].name
</div>
<div v-else> // I. Use v-if/v-else to conditionally show data, in Vue 3 there will be another feature called "suspense" borned to do those things: https://vueschool.io/articles/vuejs-tutorials/suspense-new-feature-in-vue-3/
This is Default child component
</div>
</template>
<script>
import CustomJS from '../js/custom.js';
export default
name: 'HomeContent',
props:
tools: []
,
methods:
async fetchData()
const customJs = new CustomJS();
this.tools = await customJs.getTools();
// II. The OP assigned a promise to this.tools, this.tools wasn't being assigned to any actual data at all, because:
// 1. getTools() didn't return any data
// 2. even if it returned data, it wasn't being promise-resolved (by await/then) before assigned to this.tools
,
created()
this.fetchData();
</script>
async getTools(id = 0)
this.apiTool += (id > 0) ? id : '';
try
const response = await axios.get(this.apiTool, );
console.log(response.data);
return response.data;
// III. The OP didn't return any fetched data at all, it just called API then do nothing. All the returns were returned in the arrow functions, the actual function getTools didn't get any return
catch (err)
console.log(err)
,
【讨论】:
【参考方案2】:通常为此,我使用加载器向用户显示请求正在进行中
<div v-if="loading">
<loader /> //a loader component
</div>
<div v-else>
// show the template since request finished
</div>
和脚本
export default
data: () => (
loading: false
),
created()
this.loading = true
axios.get('api') //your request
.then(response => console.log(response))
.finally(() => (this.loading = false)) //when the requests finish
如果你不喜欢上面的方式,你可以使用beforeEnter
这样路由只会在请求完成时加载:
path: '/my-route',
component: YourComponent,
props: true,
beforeEnter (to, from, next)
axios.get('api-request')
.then(response =>
to.params.data = response //we pass data through props to the component
next()
)
【讨论】:
【参考方案3】:尝试在mounted上检索数据
<template>
// try adding this condition on div element.
<div v-if="tools.length">
This is Default child component
tools[0].name
</div>
</template>
<script>
import CustomJS from '../js/custom.js';
export default
name: 'HomeContent',
props:
tools: []
,
methods:
fetchData()
const customJs = new CustomJS();
return customJs.getTools();
,
mounted: function ()
this.tools = this.fetchData();
// or
// const customJs = new CustomJS();
// this.tools = customJs.getTools();
</script>
【讨论】:
tools
未定义,和之前一样
也许您必须从父组件将新数据源分配给tools
。你能分享一下plunkr或样品吗【参考方案4】:
<template>
<div v-if="isGetTools">
This is Default child component
tools[0].name
</div>
</template>
<script>
import CustomJS from '../js/custom.js';
export default
name: 'HomeContent',
props:
tools: []
,
data: function ()
return
isGetTools: false
,
methods:
fetchData()
const customJs = new CustomJS();
this.tools = customJs.getTools();
this.isGetTools = true;
,
created()
this.fetchData(); //preferably need to wait here wait for response
</script>
尝试在您的 div 中添加 v-if。并在从 AXIOS 获取结果后将 isGetTools 更新为 true
【讨论】:
【参考方案5】:你需要从你的请求中返回一个承诺
<template>
<div>
This is Default child component
tools[0].name
</div>
</template>
<script>
import CustomJS from '../js/custom.js';
export default
name: 'HomeContent',
props:
tools: []
,
methods:
fetchData()
const customJs = new CustomJS();
return new Promise((resolve, reject) =>
customJs.getTools()
.then(res => resolve(res))
.catch(err => reject(err))
)
,
created()
this.fetchData().then(res =>
this.tools = res);
//preferably need to wait here wait for response
</script>
【讨论】:
也可以从 getTools 实现中的 axios 调用返回承诺。然后你就不必再把它包装在另一个承诺上 对不起,似乎有一些语法错误,此代码给出了构建错误。 我忘了关闭括号。再试一次【参考方案6】:您想要做的是将您的 getTools 函数定义为这样的承诺:
getTools (id = 0)
return new Promise((resolve, reject) =>
this.apiTool += (id > 0) ? id : '';
axios.get(this.apiTool,
)
.then(function (response)
console.log(response.data);
resolve(response.data);
)
.catch(function (error)
console.log(error);
reject(error)
);
)
然后你可以在你的组件代码中使用它:
<template>
<div>
This is Default child component
tools[0].name
</div>
</template>
<script>
import CustomJS from '../js/custom.js';
export default
name: 'HomeContent',
props:
tools: []
,
methods:
fetchData()
const customJs = new CustomJS();
customJs.getTools().then((result) =>
return result;
)
,
created()
this.tools = this.fetchData(); //preferably need to wait here wait for response
</script>
或者使用异步/等待:
<template>
<div>
This is Default child component
tools[0].name
</div>
</template>
<script>
import CustomJS from '../js/custom.js';
export default
name: 'HomeContent',
props:
tools: []
,
methods:
async fetchData()
const customJs = new CustomJS();
return await customJs.getTools()
,
created()
this.tools = this.fetchData(); //preferably need to wait here wait for response
</script>
【讨论】:
试过你的代码。第一种方法 -tools
未定义,但响应会记录在 fetchData()
中。第二种方法 - 我在控制台中的 created
中得到了一个 Promise<pending>
,当我将其扩展为 PromiseValue
时可以看到这些值。【参考方案7】:
试试下面的代码:这样代码只会在实际加载时呈现
<div v-if="tools">
This is Default child component
tools[0].name
</div>
【讨论】:
这样div里面的内容就不会加载了。以上是关于在 Vue.js 中等待 Ajax 响应数据的主要内容,如果未能解决你的问题,请参考以下文章