【问题标题】:Recursive async/await crashes React App递归 async/await 使 React App 崩溃
【发布时间】:2018-05-26 18:21:45
【问题描述】:

我正在尝试创建一个 React 应用程序,它使用各种参数对各种排序算法进行建模。我试图在算法的每个步骤中创建一个可变延迟,以便让它以人类可以理解的速度发生。我已经编写了这个睡眠函数来做到这一点:

sleep = (ms = this.state.delay) => {
    return new Promise(resolve => setTimeout(resolve, ms));
}

然后根据需要创建一个async 排序函数await this.sleep()。它适用于冒泡排序、选择排序和插入排序,但是当我尝试合并排序时应用程序崩溃。我认为这是由于递归,但我很困惑。

async mergeSort(arr) {
    if(arr.length < 2) {
        return arr;
    }
    const m = Math.floor(arr.length / 2);
    let left = arr.slice(0, m);
    let right = arr.slice(m);

    await this.sleep();

    return this.merge(this.mergeSort(left), this.mergeSort(right));


}

async merge(left, right) {
    let result = [];

    while(left.length && right.length) {
        if(left[0].props.number <= right[0].props.number) {
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
        await this.sleep();
    }

    while(left.length) {
        result.push(left.shift());
        await this.sleep();
    }

    while(right.length) {
        result.push(right.shift());
        await this.sleep();
    }

    return result;
}

这是我得到的错误:

Objects are not valid as a React child (found: [object Promise]). 
If you meant to render a collection of children, use an array instead.

但我没有将 Promises 分配为要渲染的元素,所以我不确定出了什么问题。

编辑:这是渲染方法:

render() {
    let {sorted, hatArray, sortingMethod, startTime, endTime, numberOfHats, sorting} = this.state;
    return (
        <div>
            <SortMenu 
                onOptionSelect={this.onOptionSelect} 
                onSortBtn={this.onSortBtn} 
                onHatInputChange={this.onHatInputChange}
                updateHatArray={this.updateHatArray}
                setDelay={this.setDelay}
                sorting={sorting}
            />
            <Modal 
                open={sorted} 
                onClose={this.onCloseModal} 
                classNames={{
                    modal: 'custom-modal',
                    closeIcon: 'modal-close-button'
                }}
                center 
            >
                <h1>Sorting Complete!</h1>
                <p>{`${sortingMethod} sorted ${numberOfHats} hats in ${(endTime - startTime) / 1000} seconds.`}</p>
            </Modal>
            <div id="hat-box">
                {hatArray}
            </div>
        </div>
    );
}

【问题讨论】:

  • 提供您的渲染方法以及那里发生的错误。
  • 完成!我想知道递归是否没有等待 Promise 解决或其他什么,所以它将未解决的 Promise 传递给 render 方法
  • 嗯,哪个方法使用了merge方法?
  • 问题是你正在渲染合并方法的结果,这是一个承诺(就像每个异步函数一样)。而是更新合并方法中的状态(每次推送后)并相应地渲染结果。
  • '我没有将 Promise 分配为元素' -- 事实上你是,mergemergeSort 隐式返回 Promise。

标签: javascript reactjs recursion async-await mergesort


【解决方案1】:

解决了!感谢 user3210641 和 Lyosha Korogada 的输入。

我更改了合并排序,因此它没有返回值,而是更改了另一个数组。然后我将状态设置为该数组。

如果将 sleep 函数放在 merge() 函数中,它会打乱排序顺序,但我可以将它放在 mergeSort() 函数中,并以可变的秒数达到相同的结果。

async mergeSort(l, r) {
    if(l < r) {
        console.log(l);
        const m = Math.floor((l + r) / 2);
        this.mergeSort(l, m);
        this.mergeSort(m + 1, r);
        await this.sleep((r - l) * this.state.delay);
        this.merge(l, m, r);    
    }
}

merge(l, m, r) {
    let left = this.globalHatArray.slice(l, m + 1);
    let right = this.globalHatArray.slice(m + 1, r + 1);
    let ptr = l;
    while(left.length && right.length) {
        if(left[0].props.number <= right[0].props.number) {
            this.globalHatArray[ptr] = left.shift();
        } else {
            this.globalHatArray[ptr] = right.shift();
        }
        ptr++;
    }

    while(left.length) {
        this.globalHatArray[ptr] = left.shift();
        ptr++;
    }

    while(right.length) {
        this.globalHatArray[ptr] = right.shift();
        ptr++;
    }
    this.setState({hatArray: this.globalHatArray});
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-28
    • 1970-01-01
    • 2017-11-08
    • 2018-02-09
    • 1970-01-01
    • 2018-03-20
    • 2017-05-13
    • 2020-07-26
    相关资源
    最近更新 更多