关于javascript:等待Vue.js中的Ajax响应数据

Wait for Ajax response data in Vue.js

我有一个Vue组件,试图在其中使用axios从API提取一些数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
   
        This is Default child component
        {{tools[0].name}}
   
</template>


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
  }
}

getTools()函数位于Vue组件文件之外的其他JS文件中,该文件使用axios.get进行API调用。

1
2
3
4
5
6
7
8
9
10
11
12
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()需要一些时间才能返回响应数据。 如何等待响应数据然后返回?


请尝试以下代码:这样,代码仅在实际加载时才会呈现

1
2
    This is Default child component
    {{tools[0].name}}


通常,我使用加载程序来向用户显示请求正在进行中

1
2
3
4
5
  <loader /> //a loader component



  // show the template since request finished

和脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
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,这样路由将仅在请求完成时加载:

1
2
3
4
5
6
7
8
9
10
11
12
{
  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()
     })
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<template>
   
        This is Default child component
        {{tools[0].name}}
   
</template>


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
  }
}

尝试在您的div中添加v-if。从AXIOS获得结果后,将isGetTools更新为true


我不知道为什么这个问题会在我的"时间轴"中弹出,并且还没有被接受的答案,所以我还是会回答。问题似乎在于对具有JS中异步代码的OP的理解。这是使它变得更好的解决方法(有3个):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<template>
   
        {{tools[0].name}}
     
     // 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
   
</template>


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();
  }
}


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)
  }
},

您要做的就是将getTools函数定义为如下所示的Promise:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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)
    });
  })
}

然后,您可以在组件代码中使用它,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<template>
   
        This is Default child component
        {{tools[0].name}}
   
</template>


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
  }
}

或使用异步/等待:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
   
        This is Default child component
        {{tools[0].name}}
   
</template>


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
  }
}


尝试检索已装载的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    <template>
    // try adding this condition on div element.
               
                    This is Default child component
                    {{tools[0].name}}
           
        </template>

       
        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();
          }
        }


您需要从请求中返回承诺

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<template>

    This is Default child component
    {{tools[0].name}}

</template>


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
    }
   }