Is it possible to string together requests in a Vue method?

Whenever a user clicks on a specific button, a request is sent to the server and an answer is received. If the user clicks on this button 100 times, I want to send 100 consecutive requests to the server. Each request must be sent after the previous one, as the response from the previous request is required for the next one.

For example:


        <button @click="sendRequest">send</button>

        methods:{

            sendRequest:function(){

                axios.post('https:/url/store-project-item', {
                    'id': this.project.id,
                    "items": this.lists,
                    'labels': this.labels,
                    'last_update_key': this.lastUpdateKey,
                    'debug': 'hYjis6kwW',
                }).then((r) => {
                    if (r.data.status) {
                        this.change = false;
                        this.lastUpdateKey = r.data.lastUpdateKey;
                        this.showAlert('success');
                    } else {
                        if (r.data.state == "refresh") {
                            this.showAlert('error');
                            this.getProject();
                        } else {
                            this.showAlert('error');
                        }
                    }
                }).catch(() => {
                    this.showAlert('error');
                });
            }
        }
    

Answer №1

I have a useful higher-order function called withMaxDOP (DOP = degrees-of-parallelism) that I use for scenarios like this:

const withMaxDOP = (f, maxDop) => {
  const [push, pop] = createAsyncStack();
  for (let x = 0; x < maxDop; ++x) {
    push({});
  }
  return async(...args) => {
    const token = await pop();
    try {
      return await f(...args);
    } finally {
      push(token);
    }
  };
};

This function relies on an async stack data structure (you can find the implementation in the provided demo), in which the pop function is asynchronous and will only resolve when there is an item available to be consumed. maxDop tokens are initially placed in the stack. Before executing the given function, a token is taken from the stack, potentially waiting if no token is immediately accessible. Once the supplied function finishes, the token is put back into the stack. This effectively controls the concurrent calls to the given function based on the number of tokens present in the stack.

You can apply this function to wrap a promise-returning (async) function and restrict re-entrancy into that function.

In your situation, you could utilize it as demonstrated below:

sendRequest: withMaxDOP(async function(){ /*await axios.post...*/ }, 1)

to ensure that one call to this function never overlaps with another.

Demo:

const createAsyncStack = () => {
  const stack = [];
  const waitingConsumers = [];
  const push = (v) => {
    if (waitingConsumers.length > 0) {
      const resolver = waitingConsumers.shift();
      if (resolver) {
        resolver(v);
      }
    } else {
      stack.push(v);
    }
  };
  const pop = () => {
    if (stack.length > 0) {
      const queueItem = stack.pop();
      return typeof queueItem !== 'undefined' ?
        Promise.resolve(queueItem) :
        Promise.reject(Error('unexpected'));
    } else {
      return new Promise((resolve) => waitingConsumers.push(resolve));
    }
  };
  return [push, pop];
};
const withMaxDOP = (f, maxDop) => {
  const [push, pop] = createAsyncStack();
  for (let x = 0; x < maxDop; ++x) {
    push({});
  }
  return async(...args) => {
    const token = await pop();
    try {
      return await f(...args);
    } finally {
      push(token);
    }
  };
};
// example usage
const delay = (duration) => {
  return new Promise((resolve) => setTimeout(() => resolve(), duration));
};
async function doSomething(name) {
  console.log("starting");
  // simulate async IO
  await delay(1000);
  const ret = `hello ${name}`;
  console.log(`returning: ${ret}`);
  return ret;
}
const limitedDoSomething = withMaxDOP(doSomething, 1);
//call limitedDoSomething 5 times
const promises = [...new Array(5)].map((_, i) => limitedDoSomething(`person${i}`));
//collect the resolved values and log
Promise.all(promises).then(v => console.log(v));

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to select just the innermost row of a nested table for emphasis?

I am working on a project with multiple nested tables and I am looking for a way to highlight the innermost row below the mouse pointer. How can I achieve this? Just to provide some context, I am using nested tables to present recursive tabular data, with ...

I just installed Electron on my Mac using the command 'sudo npm install electron -g', but now I am encountering an error. How can I resolve this issue

When I first attempted to run the command, I encountered 'Permission Denied' errors so I added sudo before the command as suggested. Another recommendation was to install the electron folder at /usr/local/lib/node_modules, but even after reinstal ...

Form input using the div element (when clicked)

I am currently working on a page that connects to a database with user information. For each user, I am creating a separate div element so that there are 6 divs total (each representing a different user). My goal is to have the ability for a user to click ...

A function designed to detect errors based on the parameters supplied as arguments

In order to ensure secure access to my restful API, I am looking to implement an authentication function called "access". I would like the function to have the following structure whenever a user interacts with the server: access(id , token ,function(err) ...

Is it possible to customize the close icons on the autocomplete feature in Material UI?

Is there a solution to change the icon while keeping its function when clicked? I am looking to replace this Icon <Autocomplete multiple id="checkboxes-tags-demo" options={top100Films} disableCloseOnSelect getOpt ...

Client event triggered twice by server

Hey there! I'm currently working on creating a simple chat app using socket.io and express. One issue I'm facing is that when a user sends a message, the server broadcasts it to the rest of the clients, but it seems to be happening twice. I can& ...

Waiting for multiple asynchronous calls in Node.js is a common challenge that many developers

I'm facing a dilemma trying to execute multiple MongoDB queries before rendering a Jade template. I am struggling to find a way to ensure that all the Mongo Queries are completed before proceeding with rendering the template. exports.init = funct ...

Firebase Error: Page Not Found

I recently set up an Angular2 application and added Firebase using npm. I successfully imported it into my app.component.ts without any errors showing up in my text editor. The package.json file also indicates that Firebase is installed correctly. However ...

Creating a Consistent Look for Italic Font Formatting in Tailwind

In an effort to establish consistent typography on a website being developed by my team, we have devised custom utility classes in Tailwind. One of these classes, small-italicized, also requires the text to be italicized. However, it seems that the fontSiz ...

In AngularJS, I've created a collection of checkboxes with a submit button ready to go

One of my goals is to make the cancel button available only when at least one job is selected. Below is my HTML View <table> <tr ng-repeat="x in jobs" ng-class-odd="'odd'" ng-class-even="'even'"> <td style="widt ...

Using an AJAX function to retrieve data from two different server-side scripts and populate two separate HTML elements on the page

My goal in this coding situation is to change values in multiple DOM targets. The example from Tizag shows the DOM being altered within the onreadystatechange function, like this: if(ajaxRequest.readyState == 4){ document.myForm.time.value = ajaxRequ ...

When using node.js and express, attempting to send an email with the packages 'nodemailer' and 'nodemailer-handlebars' may result in a TypeError being thrown, specifically [ERR_INVALID_ARG_TYPE]

I am encountering an issue while attempting to send an email using an HTML template located in the 'view' folder within the same path. The HTML template is named 'index.handlebars'. Despite believing that the path is correct, I am recei ...

[Vue Alert]: Render Error - "TypeError: Unable to retrieve the 'getters' property of an undefined object"

Here is the code snippet from my app.js file. Can someone please review it and confirm if I have defined the items correctly according to the Vuex documentation? import store from "./store"; require('./bootstrap'); window.Vue = require( ...

The $.Get method does not retain its value within an each() loop

When using the jQuery each() method on a DropDown select, I iterate through an li element. However, my $.get() function takes time to fetch data from the server, so I use a loading image that toggles visibility. The issue is that the each() method does not ...

The combination of html2canvas and jsPDF does not function properly in a Vue CLI application

I'm currently facing an issue while trying to implement jsPDF and html2canvas into my Vue CLI application. Unfortunately, it seems like the integration is not working as expected. I came across a tutorial online that served as an inspiration for me, b ...

Guide to creating standalone Express middleware that can interact with the raw request body

Can anyone help me with writing an Express middleware that can access the raw request body without affecting other handlers or middlewares? I want to achieve something like this: const middleware = [ express.raw({ type: '*/*' }), (req, res, n ...

Troubleshooting Vue component reactivity problems with async server requests

Providing some background information: Within my Vue application, I have a view called Articles. Upon mounting this component to the DOM, I use the axios library to fetch all posts from the database through Laravel controllers and API routes. In the articl ...

Dynamic cell loading in Vue using Vuetify's datatable functionality

<template> <v-data-table :headers="headers" :items="records" :items-per-page="5" show-select loading item-key="id" class="elevation-1" > <template v-slot:top> <div> <table-tabs> ...

JavaScript Email Verification

I am designing my website and encountering an issue with the email checker. I can't figure out why it's not working, especially since I have never used JavaScript before. This is what I tried: var flag=true; var st = Form1["email"].value.ind ...

Guide on integrating AJAX and coding in WordPress using PHP

I created a search box in PHP and it is functioning correctly. However, when I try to integrate it into WordPress, it does not work as expected. It seems like the AJAX functionality is not working properly within WordPress. I would like to add this search ...