如何在不同的时间间隔和使用不同的参数顺序调用异步函数

How to sequentially call an async function in various time intervals and with different arguments

我的目标是在创建订单后一段时间后逐渐增加进度条。为此,我想以不同的时间间隔和不同的参数调用下面的 updateStatus 异步函数,直到 progress 状态达到 100。下面我粘贴了进度条的代码。

链接 setTimeOutPromise 导致进度条随机增加和减少并导致应用程序变慢/冻结。处理我想要实现的目标的正确方法是什么?

const ProgressBar = ({ order }) => {
  const { status, order_date } = order;
  const msTillXSeconds = (seconds) => new Date(moment(order_date).add(seconds, 'seconds')).getTime() - Date.now();

  const [progress, setProgress] = useState(progression[status]);
  const [internalStatus, setInternalStatus] = useState(status);

  const updateStatus = async (newStatus) => {
    try {
      const body = { status: newStatus };
      const response = await fetch(`http://localhost:5000/orders/${order.order_id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json', token: localStorage.token },
        body: JSON.stringify(body),
      });
      if (response.ok) {
        setProgress(progression[newStatus]);
        setInternalStatus(newStatus);
      }
    } catch (err) {
      console.error(err.message);
    }
  };
  
  useEffect(() => {
    setProgress(progression[status]);
  }, []);

  return (
    <>
      <div className="progress">
        <div
          className="progress-bar progress-bar-striped progress-bar-animated"
          role="progressbar"
          style={{ width: `${progress}%` }}
        >
          {' '}
        </div>
      </div>
      <p className="text-center my-1">{internalStatus}</p>
    </>
  );
};

const STAGES = {
  PENDING: 'Pending Order Confirmation',
  CONFIRMED: 'Order Confirmed',
  PICKING_UP: 'Picking Up',
  EXAMINING: 'Examining',
  SANITIZING: 'Sanitizing',
  RECYCLING: 'Recycling',
};

const progression = {
  [STAGES.PENDING]: 5,
  [STAGES.CONFIRMED]: 20,
  [STAGES.PICKING_UP]: 40,
  [STAGES.EXAMINING]: 60,
  [STAGES.SANITIZING]: 70,
  [STAGES.RECYCLING]: 100,
};

您可以将不同的参数作为 setTimeout 的第三个参数传递给您的函数。

setTimeout(updateStatus, 1000, ...args)

(在我的示例中使用您的 internalStatus 作为 status

此外,由于状态处于您的状态,您可以根据您的逻辑在 useEffect() 挂钩上处理下一个 setTimeout。

useEffect(() => {

   if status something
   otherStatus = somethingElse
   updateOtherStatusAfter = ...

   setTimeout(updateStatus, updateOtherStatusAfter, otherStatus)

}, [ status ] )

观察status在useEffect的依赖列表中

这意味着每次状态发生变化时,都会触发您在 useEffect 中传递的函数。

在 Drew Reese 关于清理的评论之后,考虑这样的事情。

useEffect(() => {

  const tId = setTimeout(...)

  return () => {
     clearTimeout(tId)
  }

}, [ ... ] )

如果我对你的问题的理解正确,你想定期调用 updateStatus 并确保遵守 updateStatus 调用的顺序。

为此我看到了两个解决方案:

无论如何,您需要在组件卸载时清理这些