Javascript 为什么setTimeout不';我的冒泡排序功能(REACT)不起作用

Javascript 为什么setTimeout不';我的冒泡排序功能(REACT)不起作用,javascript,reactjs,asynchronous,Javascript,Reactjs,Asynchronous,我正在尝试可视化我的冒泡排序算法,所以我希望该算法等待50毫秒才能可视化。我尝试使用setTimeout和async函数,但它不起作用,当您删除setTimeout函数时,您可以看到数组已排序,而在函数中它就是不起作用。 该项目已安装bootstap@next和popper.js import React, { useEffect, useState, Fragment } from 'react'; import 'bootstrap/dist/css/bootstrap.css'; impo

我正在尝试可视化我的冒泡排序算法,所以我希望该算法等待50毫秒才能可视化。我尝试使用setTimeout和async函数,但它不起作用,当您删除setTimeout函数时,您可以看到数组已排序,而在函数中它就是不起作用。 该项目已安装bootstap@next和popper.js

import React, { useEffect, useState, Fragment } from 'react';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/js/bootstrap.js';
import './App.css'

function App() {
    const [values, setValues] = useState([43,4,3,56,6,3,36,56,7,5,45,34,87,99,34]);
    const [render, setRender] = useState(false)

    function forceRender() {
        setRender(true)
    }

    useEffect(() => {
        if(render) {
            setRender(false)
        }
    }, [render])

    function bubble(arr) {
        for(let j = 0, len = arr.length; j < len; j++) {
            for (let i = 0; i < len; i++) {
                if (arr[i] > arr[i + 1]) {
                    setTimeout(()=>{
                        let temp = arr[i + 1];
                        arr[i + 1] = arr[i];
                        arr[i] = temp;
                        setValues(arr);  
                    }, 50)       
                }
            }
        }
    }

    useEffect(() => {
        bubble(values)
    }, []);

    useEffect(() => {
        forceRender()
    }, [values])

    return (
        <Fragment>
            <nav className="navbar navbar-dark bg-dark">
                <div className="container">
                    <span className="navbar-brand mb-0 h1">React Sorting</span>
                </div>
            </nav>
            <div className="container sorting-container">
                <div className="row">
                    <div className="sorting">
                        {
                            values.map(e => {
                                return (
                                    <div className="bar" style={{height: `${e}%`}}>
                                        <div className="bar-text">{e}</div>
                                    </div>
                                )
                            })
                        }
                    </div>
                </div>
            </div>
        </Fragment>
    );
}

export default App;

import React,{useffect,useState,Fragment}来自'React';
导入'bootstrap/dist/css/bootstrap.css';
导入'bootstrap/dist/js/bootstrap.js';
导入“./App.css”
函数App(){
常量[值,设置值]=使用状态([43,4,3,56,6,3,36,56,7,5,45,34,87,99,34]);
const[render,setRender]=useState(false)
函数forceRender(){
setRender(真)
}
useffect(()=>{
如果(渲染){
setRender(错误)
}
},[render])
函数气泡(arr){
for(设j=0,len=arr.length;jarr[i+1]){
设置超时(()=>{
设温度=arr[i+1];
arr[i+1]=arr[i];
arr[i]=温度;
设定值(arr);
}, 50)       
}
}
}
}
useffect(()=>{
气泡(值)
}, []);
useffect(()=>{
forceRender()
},[值])
返回(
反应分选
{
values.map(e=>{
返回(
{e}
)
})
}
);
}
导出默认应用程序;

您需要提示
setTimeout
并使用
asyc
wait
来同步流程。 试试这个解决方案


import React, { useEffect, useState, Fragment } from 'react';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/js/bootstrap.js';
import './App.css'

function App() {
    const [values, setValues] = useState([43,4,3,56,6,3,36,56,7,5,45,34,87,99,34]);
    const [render, setRender] = useState(false)

    function forceRender() {
        setRender(true)
    }

    useEffect(() => {
        if(render) {
            setRender(false)
        }
    }, [render])

    function later(delay) {
        return new Promise(function(resolve) {
            setTimeout(resolve, delay);
        });
    }

    async function bubble(arr) {
        for(let j = 0, len = arr.length; j < len; j++) {
            for (let i = 0; i < len; i++) {
                if (arr[i] > arr[i + 1]) {
                    await later(50);
                    let temp = arr[i + 1];
                    arr[i + 1] = arr[i];
                    arr[i] = temp;
                    setValues(arr);    
                }
            }
        }
    }

    useEffect(() => {
        bubble(values)
    }, []);

    useEffect(() => {
        forceRender()
    }, [values])

    return (
        <Fragment>
            <nav className="navbar navbar-dark bg-dark">
                <div className="container">
                    <span className="navbar-brand mb-0 h1">React Sorting</span>
                </div>
            </nav>
            <div className="container sorting-container">
                <div className="row">
                    <div className="sorting">
                        {
                            values.map(e => {
                                return (
                                    <div className="bar" style={{height: `${e}%`}}>
                                        <div className="bar-text">{e}</div>
                                    </div>
                                )
                            })
                        }
                    </div>
                </div>
            </div>
        </Fragment>
    );
}

export default App;


从“React”导入React,{useffect,useState,Fragment};
导入'bootstrap/dist/css/bootstrap.css';
导入'bootstrap/dist/js/bootstrap.js';
导入“./App.css”
函数App(){
常量[值,设置值]=使用状态([43,4,3,56,6,3,36,56,7,5,45,34,87,99,34]);
const[render,setRender]=useState(false)
函数forceRender(){
setRender(真)
}
useffect(()=>{
如果(渲染){
setRender(错误)
}
},[render])
功能稍后(延迟){
返回新承诺(函数(解析){
设置超时(解析、延迟);
});
}
异步函数气泡(arr){
for(设j=0,len=arr.length;jarr[i+1]){
待会儿(50);
设温度=arr[i+1];
arr[i+1]=arr[i];
arr[i]=温度;
设定值(arr);
}
}
}
}
useffect(()=>{
气泡(值)
}, []);
useffect(()=>{
forceRender()
},[值])
返回(
反应分选
{
values.map(e=>{
返回(
{e}
)
})
}
);
}
导出默认应用程序;
setTimeout()是一个非阻塞函数,也就是说,它不会停止程序,直到它从超时返回。 程序中发生的情况是,第一次迭代要求setTimeout在50毫秒后进行交换,然后立即跳转到下一次迭代,下一次迭代也会这样做,所有的迭代都设置为50毫秒后运行,但彼此之间的间隔不是50毫秒

除了Prime的解决方案之外,您还可以使用一个变量,比如说
t=50
,在
if
语句中,该变量每次迭代增加50,然后将该变量的值
t
传递给setTimeout,通过这种方式,您将确保每个迭代将运行其元素交换,彼此之间的间隔至少为50毫秒

例如,请适应您的代码:

    let t = 50;

    function bubble(arr) {
        for(let j = 0, len = arr.length; j < len; j++) {
            for (let i = 0; i < len; i++) {
                if (arr[i] > arr[i + 1]) {
                    setTimeout(()=>{
                        let temp = arr[i + 1];
                        arr[i + 1] = arr[i];
                        arr[i] = temp;
                        setValues(arr);  
                    }, t)
                    t = t + 50;
                }
            }
        }
    }
设t=50;
函数气泡(arr){
for(设j=0,len=arr.length;jarr[i+1]){
设置超时(()=>{
设温度=arr[i+1];
arr[i+1]=arr[i];
arr[i]=温度;
设定值(arr);
},t)
t=t+50;
}
}
}
}

这段代码有很多问题阻碍了它的工作。举几个例子:

  • forceRender()
    函数不是必需的,也不起作用
  • useffect
    违反了一些规则。该函数同时依赖于
    bubble()
    ——任何带有类似于ESLint的linter的优秀IDE都会指出这个问题并帮助指导您。作为一种快速的解决方法,为了简单起见,我刚刚将
    bubble()
    和挂载时初始数组的设置一起移到了内部,以避免需要获取
    值的当前状态
  • 对于
    bubble()
    中的
    循环,所有
    setTimeout
    回调都指向相同的ins