【问题标题】:stop executing the loop until the function is completed停止执行循环,直到函数完成
【发布时间】:2020-03-11 13:44:54
【问题描述】:

我正在尝试在 React 中构建一个简单的游戏,我需要制作一个动画,其中一组块将其颜色更改为橙​​色,持续 1 秒,然后变回白色。这个操作需要一个一个的进行。

这是我的带有 div 数组的游戏:

假设数组是 [1,3,5,6] 我想循环遍历该数组并向每个 div 添加一个带有 bg 颜色的类一秒钟,然后将其删除

我尝试了很多东西,但我能得到的结果是所有 div 都同时改变颜色,而不是一个一个地改变

这是我的代码,它的功能是按“next lvl”和另一个异步功能开始的

const displayBlocks = async (key) => {  
    let promise = new Promise((res,rej) => {
        setTimeout(() => {
                divArray.classList.remove('active');
                res('color removed');
            }, 500)
        });
        console.log(key);
        ref.current.childNodes[key].classList.add('active'); 
        let result = await promise;     
        return result;          
}

const handleNewGame = () => {
    blockArray = []
    // generate array with random cells according to points
    for (let i = 0;i< props.points;i++) {
        let key = Math.floor(Math.random() * (props.board.length)) + 0;
        displayBlocks(key).then((res) => {
            console.log(res);
            blockArray.push(key);
        })                   
    }
    console.log(blockArray);
}

我尝试了许多异步或不异步的解决方案,但都没有奏效。你能告诉我如何在 displayBlock 函数完成之前停止循环的执行吗?

【问题讨论】:

    标签: javascript reactjs loops asynchronous animation


    【解决方案1】:

    注意:暂时无法测试,可能会遇到同样的问题

    您的displayBlocks 方法不可等待。你有没有尝试过类似的东西

    const displayBlocks = async (key) => {  
                    return new Promise((res,rej) => { // return with promise to make it awaitable
                        setTimeout(() => {
                                divArray.classList.remove('active');
                                res('color removed');
                            }, 500)
                        });
                        console.log(key);
                        ref.current.childNodes[key].classList.add('active'); 
                        let result = await promise;     
                        return result;          
    
        }
    
    
        const handleNewGame = () => {
            blockArray = []
            // generate array with random cells according to points
            for (let i = 0;i< props.points;i++) {
                let key = Math.floor(Math.random() * (props.board.length)) + 0;
                var res = await displayBlocks(key); // await should halt the loop
                console.log(res);
                blockArray.push(key);                               
            }
            console.log(blockArray);
        }
    

    【讨论】:

    • 我必须将所有代码放入返回的 Promise 中,但它起作用了!非常感谢您的帮助:D
    【解决方案2】:

    如果您在某些在线代码编辑器中分享完整的工作代码,我可以修复它,但现在,我将分享一些您可以转换为真实代码的伪代码。

    这个想法是,如果你想让你的 div 一个一个地改变颜色,那么也一个一个地添加类,在你的计算中跟踪时间。见下面的伪代码,

    function displayBlock (index) {
        let duration = 1000
        let waitTime = index * duration
        let thisDiv = divArray[index]
    
        // Now wait for waitTime amount of time before adding the OrangeClass
        setTimeout(() => {
            thisDiv.addClass('OrangeClass')
    
             //Now from this point, wait for another 1 sec and remove the OrangeClass
             setTimeout(() => {
                 thisDiv.removeCLass('OrangeClass')
             }, duration)
    
        }, waitTime)
    
    }
    

    如果你能完美地实现它,它应该可以按照你的期望工作。只是做一些试验和错误。

    你可以做到。干杯:)

    【讨论】:

    • 哇,成功了。我之前尝试过这个解决方案,但我不得不把事情搞砸,因为它没有按预期工作。但是这个解决方案的问题是延迟beetwen lightinh up next block每次都不同,可能是因为waitTime变量,但我知道它必须在那里设置超时才能工作有什么解决方法吗?
    • 我已将固定的 1000 ms 更改为名为“duration”的变量。我不明白你为什么“每次延迟都不同”,因为使用此代码,索引 0 块会立即亮起,然后在 1 秒后它会关闭,索引 1 div 会亮起,依此类推向前。所以每 1 秒后前一个 div 将关闭,下一个 div 应该打开
    • 对不起,这是我在这里的第一篇文章,感谢您的帮助:)
    • 如果它真的很有帮助,您能否将其标记为已选中,或者至少支持我的回答?这将对这项工作有很大帮助。感谢并欢迎使用 StackOverflow :)
    猜你喜欢
    • 2017-02-24
    • 2021-12-20
    • 2021-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多