使 onClick 函数等待上一个调用结束

Make an onClick function wait the previous call to end

我正在使用 React,我在连续同步点击时遇到问题(onClick 事件):

我的按钮触发了一个调用两个函数resetViewschargeViews的函数(chargeViews需要时间),所以当我快速点击两次时:

我想要的是在点击后阻止所有内容(即使用户点击我们什么都不做)并执行 resetView 然后 chargeViews 然后取消阻止以接收另一个点击并做同样的工作。

<MyButton onClick={() => {
  resetViews();
  chargeViews();
 }}> 
  Click me 
 </MyButton>

耗时函数

const chargeViews = () => {
  if(!viewsRef.current){
   ...
   reader.setUrl(url).then(()=>{
   reader.loadData().then(()=>{
   ...
   viewsRef.current = reader.getData();
})})
}}

点击太快就被忽略的功能,(点击没问题,稍等一下再点击)但是如果点击再快速点击就被忽略了。

const resetViews = () => {
  if (viewsRef.current){
   ...
   viewsRef.current = null;
}}

我不确定是否掌握了整个问题...如果不需要这么长的文本,这将是一条评论。

无论如何,只要您需要在单击按钮后禁用它,您应该在其 onclick 处理程序的开头处理它:

$(this.event.target).prop('disabled', true);

并在最后重置它:

$(this.event.target).prop('disabled', false);

总的来说,就调用要在处理程序内链式执行的多个函数而言,您所做的是正确的。但是这两个函数似乎有一个 promise 调用。在那种情况下,它们不会在链中执行,等待第一个函数完成。

因此您应该将第二次调用作为回调传递给第一次调用,以便只有在第一次调用完成其工作后才有机会调用它。

我希望有人会直截了当地建议如何使异步函数“等待”,以便无论它做什么,在调用时都会等待它完成,然后再评估下一个语句。通常这只是在其签名前添加 await 的问题,但有一些注意事项。

首先,您需要将 Promise-utilizing 函数转换为异步函数,然后在调用它们时等待它们。 这样可以更容易控制执行顺序:

const chargeViews = async () => {
  if(!viewsRef.current){
   ...
   await reader.setUrl(url);
   await reader.loadData();
   ...
   viewsRef.current = reader.getData();
  }
}

然后,您需要一个 isExecuting 引用,它在其他调用正在执行时为真,在 none 当前正在执行时为假:

const isExecuting = useRef(false);

const handleClick = async () => {
  if (!isExecuting.current) {
    // block other clicks from performing actions in parallel
    isExecuting.current = true;
    try {
      resetViews();
      await chargeViews();
    } finally {
      // unblock other clicks
      isExecuting.current = false;
    }
  }
};

最后,在您的 JSX 中使用 newly-created handleClick 函数:

<MyButton onClick={handleClick}>
  Click me
</MyButton>