Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] usePromiseQueue #2016

Closed
BigBugaboo opened this issue Dec 22, 2022 · 0 comments
Closed

[RFC] usePromiseQueue #2016

BigBugaboo opened this issue Dec 22, 2022 · 0 comments
Labels
feature New feature or request pr welcomed

Comments

@BigBugaboo
Copy link

BigBugaboo commented Dec 22, 2022

将多个并发请求,通过队列形式逐个请求,控制接口并发压力。

API

function usePromiseQueue<T = any, E = any>(): { result,  errors, queue, addQueue }

Demo

demo

import { useRef, useState, useEffect } from 'react';
import { useLatest } from 'ahooks';

type QueueType<T = any> = (...arg: any[]) => Promise<T>;

const usePromiseQueue = <T = any, E = any>() => {
  const doing = useRef(false);
  const [result, setResult] = useState<T[]>([]);
  const [errors, setErrors] = useState<E[]>([]);
  const [queue, setQueue] = useState<QueueType<T>[]>([]);
  const lastQueue = useLatest<typeof queue>(queue);

  const addQueue = (fn) => {
    setQueue([...lastQueue.current, fn]);
  };

  useEffect(() => {
    const currentQueue = lastQueue.current;

    if (currentQueue.length && !doing.current) {
      const fn = currentQueue[0];

      fn()
        .then((res) => {
          setResult([...result, res]);
        })
        .catch((err) => {
          setErrors([...errors, err]);
        })
        .finally(() => {
          doing.current = false;
          lastQueue.current.shift();
          setQueue([...lastQueue.current]);
        });
      doing.current = true;
    }
  }, [queue]);

  return { result, errors, queue, addQueue };
};

const App = () => {
  const { result, addQueue } = usePromiseQueue();

  const handleRequest = () => {
    addQueue(() => {
      return new Promise((resolve) =>
        setTimeout(() => {
          resolve('response');
        }, 2000)
      );
    });
  };

  return (
    <div>
      {result.map((text) => (
        <div key={text}>{text}</div>
      ))}
      <button onClick={handleRequest}>add request</button>
    </div>
  );
};

export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request pr welcomed
Projects
None yet
Development

No branches or pull requests

2 participants