首页 > 解决方案 > 反应超时竞争条件

问题描述

updatePixelBuffer(x, y) {
    console.log("cleared from update", this.state.pixelRefreshTimer);
    window.clearTimeout(this.state.pixelRefreshTimer);

    let pixelRefreshTimer = window.setTimeout(() => {
        console.log("from timer", pixelRefreshTimer);
        this.triggerPixelRefresh();
    }, 3000);
    console.log("set timer", pixelRefreshTimer);

    this.setState({
        pixelRefreshTimer: pixelRefreshTimer,
    });

    // store operation in buffer and perform visual draw
}

triggerPixelRefresh() {
    console.log("cleared from refresh", this.state.pixelRefreshTimer);
    window.clearTimeout(this.state.pixelRefreshTimer);

    // update data structure with operations in buffer
}

大多数情况下,updatePixelBuffer 会被多次调用,因为我使用它来存储绘图操作,然后在数据结构上批量更新它们,我允许用户实时可视化绘图操作(即使数据结构还没有更新)。

当我想在调用 updatePixelBuffer(x, y) 后立即调用 triggerPixelRefresh() 时,我的困境就开始了。计时器不应在此呼叫后启动。

updatePixelBuffer(1, 2);
triggerRefresh();

由于 setState 是异步的,所以我不知道如何保证 triggerPixelRefresh() 中的 window.clearTimeout 会在 updatePixelBuffer 中新设置的计时器被一个接一个地调用时清除它们。我不确定使用什么模式来保证这一点。

updatePixelRefresh 设置了一个计时器,以便如果以后不调用 triggerPixelRefresh,它将被调用。这是为了保证缓冲区中的操作是在以后进行的。triggerRefresh 需要取消该计时器并立即使用存储的操作更新数据结构。我需要防止在不可预测的时间调用刷新。

从技术上讲,我可以直接修改状态以使它们同步运行,但我不希望这样做。

标签: reactjsasynchronous

解决方案


setState(state,callback)为此存在重载:保证callback在状态改变后被调用。

话虽如此,您可以将您的转换updatePixelBuffer为返回一个在被调用Promise时解析的。callback

此外,您triggerPixelRefresh还可以返回一个立即解决的承诺。

最后,将它们都包装在函数中,让函数暴露triggerPixelRefreshPromise解析方法,您可以在之后调用该方法。

最后,将两个 Promise 都包装在Promise.race([p1,p2]).

所做Promise.race(p1,p2)的是它将p1,p2解决首先解决的任何一个承诺(换句话说,超时或您的直接调用)。

也看看这个: Understanding promise.race() usage


推荐阅读