javascript 在 Vue.js 中等待 Ajax 响应数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/51322046/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 09:31:11  来源:igfitidea点击:

Wait for Ajax response data in Vue.js

javascriptvue.jsaxios

提问by Souvik Ghosh

I have a Vue component where I am trying to fetch some data from an API using axios.

我有一个 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>

The getTools()function is in a different JS file outside the Vue component file which makes the API call using axios.get.

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

The problem is, {{tools}}is undefined since the getTools()takes some time to return the response data. How can wait for the response data and then return?

问题是,{{tools}}未定义,因为getTools()返回响应数据需要一些时间。如何等待响应数据然后返回?

回答by Surya Neupane

Try the code below: so the code will render only when its actually loaded

试试下面的代码:这样代码只会在它实际加载时呈现

<div v-if="tools">
    This is Default child component
    {{tools[0].name}}
</div>

回答by markcc

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

Try to add v-if in your div. And update the isGetTools to true after getting the result from AXIOS

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

回答by roli roli

Usually for that, I am using a loader to show the user that a request is in progress

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

<div v-if="loading">
  <loader /> //a loader component
</div>

<div v-else>
  // show the template since request finished
</div>

and the script

和脚本

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
  }

}

If you don't like the way above, you can use beforeEnterso the route will load only when the request finishes:

如果你不喜欢上面的方式,你可以使用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()
     })
  }
}

回答by Loi Nguyen Huynh

I don't know why this question pops up in my "timeline" and haven't got the accepted answer yet so I'll answer it anyway. The problem seemed to be with the understanding of the OP with asynchronous code in JS. Here's the fix (there're 3) to make it better:

我不知道为什么这个问题会出现在我的“时间线”中并且还没有得到公认的答案,所以我还是会回答。问题似乎在于对 OP 与 JS 中的异步代码的理解。这是修复(有 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)
  }
},

回答by Dionisis Karakasiliotis

You need to return a promise from your request

你需要从你的请求中返回一个承诺

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

回答by Hardik

Give a try to retrieve data on 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>

回答by Imre_G

What you want to do is to define your getTools function as a promise like this:

您想要做的是将您的 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)
    });
  })
}

Then you can use it in your component code as:

然后你可以在你的组件代码中使用它:

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

Or using async/await:

或者使用异步/等待:

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