如何在不同的时间间隔和使用不同的参数顺序调用异步函数
How to sequentially call an async function in various time intervals and with different arguments
我的目标是在创建订单后一段时间后逐渐增加进度条。为此,我想以不同的时间间隔和不同的参数调用下面的 updateStatus
异步函数,直到 progress
状态达到 100。下面我粘贴了进度条的代码。
链接 setTimeOut
和 Promise
导致进度条随机增加和减少并导致应用程序变慢/冻结。处理我想要实现的目标的正确方法是什么?
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 调用的顺序。
为此我看到了两个解决方案:
- 递归调用 updateStatus(即在函数末尾添加一个 setTimeout(...))
- 使用 promise 队列(如 https://www.npmjs.com/package/queue-promise)并使用 setInterval
推送到它
无论如何,您需要在组件卸载时清理这些
我的目标是在创建订单后一段时间后逐渐增加进度条。为此,我想以不同的时间间隔和不同的参数调用下面的 updateStatus
异步函数,直到 progress
状态达到 100。下面我粘贴了进度条的代码。
链接 setTimeOut
和 Promise
导致进度条随机增加和减少并导致应用程序变慢/冻结。处理我想要实现的目标的正确方法是什么?
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 调用的顺序。
为此我看到了两个解决方案:
- 递归调用 updateStatus(即在函数末尾添加一个 setTimeout(...))
- 使用 promise 队列(如 https://www.npmjs.com/package/queue-promise)并使用 setInterval 推送到它
无论如何,您需要在组件卸载时清理这些