0

I have a imported component, she calls a function every time that user do something (lets say press on button), in the function i must to fetch some data in async order, i would like to run the function calls as async way, the calls to the function will wait until the function is finished and then call the function again. code example- if i trigger the function 3 times fast:

hadlechange = async(type:string) => {
  console.log(1111111)
  let storage = await getData("G");
  console.log(22222222)

    await bla1();
    await bla2();
    console.log(333333)

  await storeData('blabla');
  console.log(4444444)
};

render() {
  return (
    <BlaBla onChange ={this.hadlechange}>)
    }

Expected results

11111
22222
3333
4444
1111
2222
3333 
4444
1111
2222
3333 
4444

What i get

1111
1111
2222
2222
1111
3333
2222
4444
3333
3333
4444
4444

I use JavaScript- React for the client

0

2 Answers 2

1

Thanks to @Proximo i thought about this solution and it's works fine. Maybe someone else will find it helpful so i share my code :)

  constructor() {
    this.notHandling = true;
    this.saves = [];
  }

  onChange = async (status: string) => {
    this.saves.push(status);
    if (this.notHandling) {
      this.notHandling = false;
      while (saves.length > 0) {
        await blabla1(saves.pop());
         ...
      }
      this.notHandling = true;
    }
  };

  render() {
    return (
      <BlaBla onChange ={this.hadlechange}>)
      }

Edit

As a help function

 export const handleMultiAsyncCalls = func => {
  let notHandling = true;
  let saves = [];
  return async function() {
    const args = arguments;
    const context = this;
    saves.push(args);
    if (notHandling) {
      notHandling = false;
      while (saves.length > 0) {
        await func.apply(context, saves.pop());
      }
      notHandling = true;
    }
  };
};

In your class you call it this way-

 constructor(props) {
    super(props);
    this.handleMultiCalls = handleMultiAsyncCalls(blablaFunc);

  handleChange = (data: string) => {
    this.handleMultiCalls(data);
  };
Sign up to request clarification or add additional context in comments.

2 Comments

Nicely done, now you can abstract that pattern out as a helper function.
Cool, are you a C# developer too? Let me show you how I'd do the same in an edit.
1

What's happening is that multiple changes are happening at once. An easy fix is to set a global flag to prevent the event method while the current action is in-progress.

constructor() {
   this.notHandling = true;
}

hadlechange = async(type:string) => {
  if (this.notHandling) {
     this.notHandling = false;
     console.log(1111111)
     let storage = await getData("G");
     console.log(22222222)

     await bla1();
     await bla2();
     console.log(333333)

     await storeData('blabla');
     console.log(4444444)
     this.notHandling = true;
  }
};

Edit: Helper class example

class AsyncQueue {
    private queue: Function[];
    private processing: boolean;

    constructor() {
        this.queue = [];
        this.processing = false;
    }

    push = (method:any) => {
        this.queue.push(method);
        this.process();
    }

    private process = async () => {
        if (!this.processing) {
           this.processing = true;
           for (let action of this.queue) {
              await action();
           }
           this.processing = false;
        }
    }
}

export const asyncQueue = new AsyncQueue;

Using Helper

// import example...
import { asyncQueue } from '~/common/helpers';

// Async test method
const tester = (message: string, seconds: number = 1) => {
    return new Promise((resolve) => {
        console.log('start ' + message);
        setTimeout(() => {
            console.log(message);
            resolve(message);
        }, seconds * 1000);
    });
};

// Method calls
asyncQueue.push(() => tester('FIRST'));
setTimeout(() => asyncQueue.push(() => tester('SECOND', 2)), 50);
asyncQueue.push(() => tester('THIRD', 4));

2 Comments

Thank you for the response but it didn't help me , i want it to fetch the data multiple times - if i will do like this it can fetch it just once.. I want it to wait until the previous calls finish and then call it
But you want them to fire in sequence, correct? You can store your requests in a queue (a simple array) to ensure each event fired executes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.