开发者问题收集

处理对异步函数的多个调用

2020-04-18
378

我有一个导入的组件,每次用户执行某项操作(比如说按下按钮)时,它都会调用一个函数,在函数中我必须以异步顺序获取一些数据,我想以异步方式运行函数调用,对函数的调用将等到函数完成后再调用该函数。 代码示例 - 如果我快速触发该函数 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- React 作为客户端

2个回答

感谢@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);
  };
Barak
2020-04-18

实际发生的情况是多个更改同时发生。一个简单的解决方法是设置一个全局标志,以在当前操作正在进行时阻止事件方法。

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));
Proximo
2020-04-18