【问题标题】:How to wait for the whole recursion to finish before moving on in Javascript?如何在继续使用 Javascript 之前等待整个递归完成?
【发布时间】:2020-08-16 08:22:06
【问题描述】:

我是 reactJS 的新手,正在尝试构建一个排序可视化工具。我面临的问题是在实现 quickSort() 例程时。
我的 quickSort() 例程如下:

async quickSort(array, p, r) {
         if(p<r){
                this.Partition(array,p,r).then((q)=>{
                console.log(p, ' ', r)
                this.quickSort(array, p, q-1)
                this.quickSort(array,q+1,r)

                })  
            }   
    }

我有一个 .then 和 Partition 函数的原因是因为我在 Partition 例程中使用 async/await 来制作动画。然后分区例程返回分区“q”的值,然后可以进行递归。 Partition 函数返回一个promise,它的值是分区值'q',没有它递归就不能继续,因此是'.then'部分。

现在,代码运行正常,但我想添加更多功能。我从 quickSortHelper() 例程内部调用这个 quickSort() 例程。在 quickSortHelper() 我首先禁用一个按钮,然后调用 quickSort() 并在完成 quickSort() 后我想再次启用该按钮。 但问题是 quickSort(array, 0 , n-1) 仅在第一次调用后返回,因此该按钮立即被禁用和启用,而无需等待整个递归展开。

我尝试从 quickSort() 内部返回一个承诺,以确保当承诺得到解决时,我们才会继续启用按钮。但是承诺会在 1-2 次迭代后解决(这是有道理的,因为我认为函数会返回 p>r 的时刻),因此按钮无需等待整个递归完成即可启用。

对于如何解决这个问题,有任何的建议吗?有没有办法暂停执行,直到 quickSort() 完成,然后继续启用按钮的工作?

async quickSortHelper(){
        this.setState({generateButton: true})
        console.log(this.state.generateButton)

        var array = this.state.array

        this.quickSort(array, 0, array.length-1 ).then(()=>{
            this.setState({array})
            this.setState({generateButton: false})
        })
    }

还有一件事,console.log(this.state.generateButton) 输出 false。所以它永远不会将状态设置为true?我不明白为什么会这样?

【问题讨论】:

  • 你应该把await放在返回一个promise的表达式之前。但是如果没有看到你是如何实际创建和解决承诺的,就不可能说这就是你所要做的。与其用文字描述您的 quickSort 相关函数的功能(如分区、帮助器...),不如只发布代码(但不超过重现问题所需的内容)就不会那么模棱两可了
  • 不是等待提供与使用 .then 相同的功能吗?这是除了仅选择分区索引的分区例程之外的整个代码。辅助函数在最后。
  • 要检查this.state.generateButton是否返回false,请分享设置状态的代码(this.setState

标签: javascript arrays reactjs asynchronous-javascript


【解决方案1】:

您的quickSort 函数当前返回一个立即解析为未定义值的承诺。您需要返回一个承诺,并await 解决它。所以要么继续then 链(然后你就不需要async),或者使用async/await(比较下):

function quickSort(array, p, r) {
    if (p < r) {
        return this.Partition(array,p,r).then((q) => {
    //  ^^^^^^
            console.log(p, ' ', r);
            return this.quickSort(array, p, q-1);
    //      ^^^^^^
        }).then(() => {
            return this.quickSort(array,q+1,r);
    //      ^^^^^^
        });
    }   
}

当然,混合asyncthen 有点奇怪,所以你也应该用await 语法替换then

async quickSort(array, p, r) {
    if (p < r) {
        let q = await this.Partition(array,p,r);
        console.log(p, ' ', r);
        await this.quickSort(array, p, q-1);
        await this.quickSort(array,q+1,r);
    }   
}

注意:使用分号。当您可以自己控制时,依赖自动分号插入就是放弃控制。

【讨论】:

  • 是的,我同意我应该坚持仅使用 await 或仅使用 then 以使代码更具可读性。我尝试实现您的建议,但我收到一个解析错误,提示“无法在异步函数之外使用 await”。 (这是我尝试使用 return 语句建议的第一件事)
  • 第二个完成了这项工作!!我错过了快速排序的等待,没有意识到正在返回一个未定义的值!谢谢!
  • 确实,第一个版本应该真正延续then 链。查看第一个版本的更新。
【解决方案2】:

这应该可以完成工作:

async quickSort(array, p, r) {
    if(p<r){
        const q = await this.Partition(array,p,r);
        console.log(p, ' ', r);
        await this.quickSort(array, p, q-1);
        await this.quickSort(array,q+1,r);
    }
}

【讨论】:

    猜你喜欢
    • 2021-06-26
    • 2015-09-16
    • 2020-02-24
    • 1970-01-01
    • 1970-01-01
    • 2019-03-12
    • 2010-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多