Обработка нескольких вызовов функции asyn c - PullRequest
0 голосов
/ 18 апреля 2020

У меня есть импортированный компонент, она вызывает функцию каждый раз, когда пользователь что-то делает (скажем, нажимает на кнопку), в функции я должен получить некоторые данные в асинхронном порядке c, я хотел бы запустить функцию вызовы asyn c, вызовы функции будут ждать, пока функция не завершится, а затем вызовут функцию снова. Пример кода - если я вызову функцию в 3 раза быстрее:

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}>)
    }

Ожидаемые результаты

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

Что я получу

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

Я использую JavaScript - Реагировать на клиента

Ответы [ 2 ]

1 голос
/ 18 апреля 2020

Благодаря @Proximo я подумал об этом решении, и оно отлично работает. Может быть, кто-то еще найдет это полезным, поэтому я делюсь своим кодом:)

  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}>)
      }

Редактировать

В качестве справочной функции

 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;
    }
  };
};

В ваш класс вы называете это так-

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

  handleChange = (data: string) => {
    this.handleMultiCalls(data);
  };
1 голос
/ 18 апреля 2020

То, что происходит, - то, что многократные изменения происходят одновременно. Простое решение - установить глобальный флаг для предотвращения метода события во время выполнения текущего действия.

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;
  }
};

Редактирование: пример класса помощника

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;

Использование помощника

// 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));
...