Justanuser2020
Justanuser2020

Reputation: 47

Why does this computed property return 'promise {<pending>'?

I am learning Vue Js and I want to develop a small application with which I bring different data according to what I select in a dropdown.

The problem I am having is that when I want to see what I am bringing (by console) with a computed property, it shows me 'promise {', which inside it is the data with which I want to work, but being in 'pending' I can't extract and use them.

This is the application that I have developed so far, which brings news depending on the section that is entered:

    <template>
      <div>
        <div v-for="new in totalNews" :key="new.id">
        </div>
      </div>
    </template>
    
    <script>
    export default {
      name: "Home",
      data() {
        return {
          news: [],
        };
      },
      methods: {
        async getNews() {
    
         const param = this.$route.params.id;
          await this.axios
          .get("http://localhost:8080/api/v1/newsBySelection/" + id)
          .then((res) => {
            this.news = res.data;
          })
          .catch((error) => {
            console.log(error);
          });
      },
      computed: {
        totalNews() {
          let news = this.getNews()
          console.log(news);
          return news;
        },
      },
    };
    </script>

Here is a sample of what I get on the console when running this application, as you can see every time I select a section of the diamond brings me the corresponding news, but in the form of promises:

https://i.postimg.cc/XqtHBZfL/imagenparasubir.png

I already appreciate any kind of help !!

Upvotes: 2

Views: 2430

Answers (3)

muka.gergely
muka.gergely

Reputation: 8329

This is not really a Vue question, but a general Javascript topic: how do asynchronous calls work, what is a Promise & how does async/await simplify the syntax.

Here's a small snippet to show you a possible solution using Promise to display a list of items obtained from an API endpoint:

new Vue({
  el: "#app",
  data() {
    return {
      // we init a variable that is going to hold
      // the values that we expect to receive from
      // the API endpoint
      news: [],
    }
  },
  methods: {
    getNews() {
      fetch('https://jsonplaceholder.typicode.com/todos')
        .then(response => response.json())
        .then(json => {
          // the data is added to our component data
          // when it arrives from the API endpoint
          this.news = json
        })
    },
  },
  mounted() {
    // we query the API endpoint when the component
    // is mounted in the DOM
    this.getNews()
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div v-for="article in news" :key="article.id">
    {{ article.title }}
  </div>
</div>

UPDATE

There's one implicit thing in the snippet: why is it a solution using Promise? Where's the Promise in the snippet?

[fetch] returns a Promise that resolves to the Response to that request

Source: MDN Fetch API

This is why we can use .then() after fetch() - fetch always returns a Promise.

Upvotes: 0

Matt U
Matt U

Reputation: 5118

getNews is an async function. Although it doesn't actually return anything, it being async means it's a Promise. What's happening in your totalNews computed is that you're getting the promise object which represents this.getNews(), so the behavior you're seeing makes sense. Your computed probably should not be calling a method that modifies the component's state. The point of a computed is to return a value based on one or more properties in the component.

Instead, call this.getNews() in the mounted lifecycle hook:

<script>
  export default {
    name: "Home",
    // ...
    mounted() {
      this.getNews()
    }
  }
</script>

There's no need to use a computed at all here, because you just want to display all the objects in the data. So this becomes:

<template>
  <div>
    <div v-for="item in news" :key="item.id">
    </div>
  </div>
</template>

I also changed new to item, because new is actually a keyword in JavaScript.

Update

It's fine to use computed properties if you want to filter based on a user selection. Something such as this:

computed: {
  filteredNews() {
    return this.news.filter(item => item.someProperty === this.selectedOption);
  }
}

Upvotes: 2

David Min
David Min

Reputation: 1414

You'll probably benefit from reading how Promise object works conceptually.

To your purpose, you might find using the .then() method useful - it essentially will call back to the code inside after the promise has resolved.

Because you are using an async function, the work is on a separate thread. If you are trying to get the value in a separate thread, it won't know when the data has been loaded.

Upvotes: 1

Related Questions