Vue.js实现快速排序可视化遇async/await问题求助
解决Vue.js快速排序可视化中的async/await递归问题
嘿,我完全懂你遇到的困扰!你推测递归里的async/await是问题根源,这个判断太准啦~咱们一步步拆解问题,然后把它修好。
问题核心分析
你的quickSort是同步函数,但它调用的partition却是异步函数(带async/await)。这就导致:
quickSort不会等partition完成分区和交换操作,就直接执行后面的递归调用,整个排序的逻辑顺序彻底乱套了;sortArray里直接把quickSort的返回值赋值给numArray,但quickSort同步执行时,partition里的异步交换还没开始,所以numArray一开始还是原数组,后续异步操作才慢慢修改数组,导致UI更新和排序节奏完全不匹配。
修复方案
我们只需要把递归的quickSort也改成异步函数,并用await等待每一步异步操作完成,让排序逻辑按顺序执行:
1. 修改quickSort为异步函数
async function quickSort(arr, left, right) { var len = arr.length, pivot, partitionIndex; if (left < right) { pivot = right; // 等待分区操作完成,拿到正确的partitionIndex partitionIndex = await partition(arr, pivot, left, right); // 等待左右子数组的排序完成,保证顺序正确 await quickSort(arr, left, partitionIndex - 1); await quickSort(arr, partitionIndex + 1, right); } return arr; }
2. 修改sortArray方法为异步函数
async sortArray: function(event) { // 等待整个排序过程完成 await quickSort(this.numArray, 0, this.numArray.length - 1); console.log(this.numArray); }
3. (可选优化)避免函数名冲突
你的Vue组件方法shuffleArray和全局函数shuffleArray同名了,虽然能工作,但容易混淆,建议把全局函数改名:
// 全局函数改名 function shuffle(arr) { var currentIndex = arr.length, temporaryValue, randomIndex; while (0 !== currentIndex) { randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1; temporaryValue = arr[currentIndex]; Vue.set(arr, currentIndex, arr[randomIndex]); Vue.set(arr, randomIndex, temporaryValue); } return arr; } // 组件方法里调用改名后的函数 shuffleArray: function(event) { var tempArray = shuffle([...this.numArray]); // 复制数组再打乱,避免修改原数组时的响应式问题 this.numArray = tempArray; }
完整修复后的代码
这里把所有修改整合到一起,你可以直接用:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>JS Bin</title> <style> body { font-family: sans-serif; font-size: 12px; font-weight: 700; } .container { display: block; clear: both; overflow: hidden; } .el { border: 1px solid lightgray; float: left; width: 2%; text-align: center; padding: 10px 0; width: 25px; margin: 0 2px; } .btn { display: block; margin-top: 20px; clear: both; border: 2px solid orange; text-align: center; padding-top: 10px; padding-bottom: 10px; cursor: pointer; text-decoration: none; color: black; } </style> </head> <body> <div id="app"> <div class="container" id="scene1"> <div class="el" v-for="item in numArray">{{ item }}</div> </div> <a href="#" v-on:click.prevent="fillArray" class="btn">Fill array</a> <a href="#" v-on:click.prevent="shuffleArray" class="btn">Shuffle array</a> <a href="#" v-on:click.prevent="sortArray" class="btn">Sort array</a> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script> <script> // noprotect var app = new Vue({ el: '#app', data: { numArray: [] }, methods: { fillArray: function(event) { this.numArray = []; // 先清空,避免重复填充 for (var i = 0; i<30; i++) { this.numArray.push(i); } }, shuffleArray: function(event) { var tempArray = shuffle([...this.numArray]); // 复制数组再打乱,避免修改原数组时的响应式问题 this.numArray = tempArray; }, async sortArray: function(event) { await quickSort(this.numArray, 0, this.numArray.length - 1); console.log(this.numArray); } } }) Vue.config.devtools = false; function sleep(ms = 0) { return new Promise(r => setTimeout(r, ms)); }; function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } function shuffle(arr) { var currentIndex = arr.length, temporaryValue, randomIndex; while (0 !== currentIndex) { randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1; temporaryValue = arr[currentIndex]; Vue.set(arr, currentIndex, arr[randomIndex]); Vue.set(arr, randomIndex, temporaryValue); } return arr; } async function quickSort(arr, left, right) { var len = arr.length, pivot, partitionIndex; if (left < right) { pivot = right; partitionIndex = await partition(arr, pivot, left, right); await quickSort(arr, left, partitionIndex - 1); await quickSort(arr, partitionIndex + 1, right); } return arr; } async function partition(arr, pivot, left, right) { var pivotValue = arr[pivot], partitionIndex = left; for (var i = left; i < right; i++) { if (arr[i] < pivotValue) { swap(arr, i, partitionIndex); await sleep(100); partitionIndex++; } } swap(arr, right, partitionIndex); await sleep(100); return partitionIndex; } function swap(arr, i, j) { var temporaryValue = arr[i]; Vue.set(arr, i, arr[j]); Vue.set(arr, j, temporaryValue); } </script> </body> </html>
为什么这样改能解决问题?
- 把
quickSort改成异步函数后,每一步的partition和递归调用都需要await等待完成,这样排序逻辑就会按正确的顺序执行:先完成当前分区的所有交换,再递归排序左右子数组; sortArray用await等待整个排序过程结束,确保UI能实时跟随每一步交换更新,不会出现逻辑和UI脱节的情况。
内容的提问来源于stack exchange,提问作者Maxim
相关产品推荐
相关产品推荐

