How to turn several asynchronous requests into synchronous?

Asked

Viewed 581 times

3

How could I perform the function sortOrder as soon as the function getOrders complete all requests?

The idea is to sort all orders by latest purchase date.

Code

mounted () {
    this.user = this.$q.localStorage.get.item('userInfo')
    axios.get(`${api.getOrders}${this.user.cpf}`).then(response => {
      this.orders = response.data
      if (this.orders !== '') {
        this.$q.loading.show()
        this.getOrders(callback => {
          this.sortOrder()
        })
      }
    })
  },
  methods: {
    getOrders: function () {
      for (let i = 0; i < this.orders.length; i++) {
        axios.get(api.obterOrderInfo(this.orders[i].orderId)).then(response => {
          this.orderInfo = this.orderInfo.concat(response.data)
        })
      }
    },
    sortOrder: function () {
      this.orderInfo.sort(this.compare)
      this.$q.loading.hide()
    },
    compare: function (x, y) {
      return x.creationDate < y.creationDate
    }
}

1 answer

4


The "Vue-like" solution, that is, using the reactivity that Vue offers, is to sortOrder one computed Property that depends on this.orderInfo. This makes the code of sortOrder is run whenever this.orderInfo change. Note that the .sort() changes the original array, this can give unwanted effects in particular in a reactive environment as in Vue...

Actually, thinking that way, I’d give new names and do the thing like this:

module.exports = {
  data() {
    return {
      orders: [],
      orderInfo: [],
    }
  },
  mounted() {
    this.user = this.$q.localStorage.get.item('userInfo')
    axios.get(`${api.getOrders}${this.user.cpf}`).then(response => {
      this.orders = response.data;
    })
  },
  computed: {
    sortedOrder() {
      return this.orderInfo.slice().sort(this.compare);
    }
  },
  watch: {
    orders() {
      if (this.orders.length > 0) {
        this.$q.loading.show();
        this.getOrders();
      }
    },
    sortedOrder() {
      this.$q.loading.hide();
    }
  },
  methods: {
    getOrders: function() {
      const orders = this.orders.map(order => {
        const endpoint = api.obterOrderInfo(order.orderId);
        return axios.get(endpoint).then(response => response.data)
      });
      Promise.all(orders).then(orderInfo => this.orderInfo = orderInfo);
    },
    compare: function(x, y) {
      return x.creationDate < y.creationDate
    }
  }
};
  • 1

    You should call the function getOrders in the Mounted?

  • 1

    @Marconi sorry I was on the train and I got no reception. Yes the this.getOrders() has to be called, but within the watch. So he is called whenever the orders change. It may take a debauchery, but I think it serves your case.

  • 1

    Along those lines Promise.all(orders)... Orders is Undefined, something I should add to the @Sergio code?

  • @Marconi forgot a return before axios.get. I corrected you now.

  • 2

    Now yes hehehe, thank you very much @Sergio, great learning here :)

  • The only question I was left with was here Promise.all(orders).then(orderInfo => this.orderInfo = orderInfo);. I understood that you add all the requests in an array and as soon as they respond you add them in orderInfo, that would be the logic?

  • 2

    @Exact Marconi! The Promise.all transforms an asynchronous array into a synchronous array. What is given to you in .then(orderInfo is the array in the same order as the files inside orders. When the Promise.all has run all these events gives the result of these then. You should also have a .catch() to catch the mistakes, but I think you know that.

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.