'Vue send request until get result from another one

I'm from Ruby language so sorry for noob question or if my concept is wrong - please tell me.

In my Vue application user should provide some data and asynchronously get the result below the form. The flow is like:

  1. user provides input data
  2. the app sends POST request (createProductsRequest) to Rails backend app
  3. Vue get response with load_id which represents id of newly created record e.g. 12345 - sample json: { load_id: 12345 }
  4. Vue app use load_id and send GET request (fetchSyncedProductsResultRequest) to Rails backend app endpoint (sample json: {result: [{test: 'test'}]})
  5. check if response.result is nil ({result: nil}), if yes resent request until it will not be nil
  6. display response data

The question is where (and how actually) to put the loop from step 5 that checks if a given response from step 4 does not contain null? Vue should stop sending requests when response is not nil.

Here's what I've produced so far:

import.js

const createProductsRequest = (self, products) => {
  const jwtToken = self.$store.state.idToken;
  const payload = JSON.stringify({ product_codes: products['product_codes'].split(',') })

  return axios
    .post(`/api/v1/imports/products_batches`, payload,{
      headers: {
        Authorization: `Bearer ${jwtToken}`,
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      }
    })
    .then(response => response.data)
};

const fetchSyncedProductsResultRequest = (token, id) => {
  return axios
    .get(`/api/v1/imports/products_batches`, {
      params: { id: id },
      headers: {
        Authorization: `Bearer ${token}`,
      }
    })
    .then(response => {
      return response.data['result']
    })
};

sync_products.vue

<template>
  <div class="col-12 col-md-3">
    <button
      type="button"
      class="btn btn-primary"
      @click="syncProducts"
    >
      Sync
    </button>
  </div>
</template>

<script>

    import {
      fetchSyncedProductsResultRequest,
      createProductsRequest
    } from '../../api/imports'
    
    export default {
      name: 'SyncProducts',
      data() {
        return {
          fetchedProductSyncStatus: [],
          load_id: ''
        }
      },
      async mounted() {
        await fetchSyncedProductsResultRequest(this, id)
        this.syncedProductsFetched = true
        this.pageChanged(this.currentPage)
      },
      async mounted() {
        const jwtToken = this.$store.state.idToken;
        fetchSyncedProductsResultRequest(jwtToken).then(data => {
          this.fetchedProductSyncStatus = data
        })
      },
      methods: {
        async syncProducts() {
          let confirmationText = `Do you want to ${this.productsToSyncAmount} sync products?`
    
          if (this.productsToSyncAmount === 0) {
            ModalController.showToast('', 'Type product codes for sync first, please!', 'warning')
          }
          else if (await ModalController.showConfirmation('Confirmation', confirmationText)) {
            try {
              ModalController.showLoader()
              await createProductsRequest(this, this.styleCodes)
              const successMessage = `${this.productsToSyncAmount} products have been queued for sync`
              await ModalController.showToast('', successMessage)
            } catch (data) {
              const errorMessage = `Error occurred during queueing products to sync - `
              ModalController.showToast('', errorMessage + data?.message, 'error')
            } finally {
              this.styleCodes = []
              ModalController.hideLoader()
            }
          }
        },
      }
    }
</script>


Solution 1:[1]

To spare your backend i'd probably wait x amount of time (enough for the backend to have created the resource) and then send the get request - instead of potentially spamming it.

With that said i think you want to use the setTimeout function to call a function that makes the API call. There you can make the call, check if result is nil and then use setTimeout and call the function again if needed. Like so:

async loadId() {
  const data = await makeApiRequest()
  if (!data.result) {
    setTimeout(this.loadId, waitTimeInMillis);
    return;
  }
  //Do what you want if when result isn't null.
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Lars