日常开发记录
日常开发记录
- 1.for循环的打断特定循环
- 示例1:跳出嵌套循环
- 示例2:使用continue跳到外层循环
- 2.同步请求阻塞主线程
1.for循环的打断特定循环
看到了一段这个代码,第一次见
在 JavaScript 中,当我们需要从嵌套循环中跳出时,普通的 break 语句只能跳出当前循环。而标签语法(Labeled Statements)提供了一种更灵活的方式,允许我们从多层嵌套的循环中直接跳出。
示例1:跳出嵌套循环
console.log("示例1输出:");
outerLoop: for (let i = 0; i < 3; i++) {for (let j = 0; j < 3; j++) {if (i === 1 && j === 1) {console.log(`在i=${i}, j=${j}时跳出整个外层循环`);break outerLoop;}console.log(`i=${i}, j=${j}`);}
}
示例1输出:
i=0, j=0
i=0, j=1
i=0, j=2
i=1, j=0
在i=1, j=1时跳出整个外层循环
注意:没有i=1,j=2和任何i=2的迭代,因为整个循环被终止了。
示例2:使用continue跳到外层循环
console.log("示例2输出:");
outerLoop: for (let i = 0; i < 3; i++) {console.log(`开始i=${i}的迭代`);for (let j = 0; j < 3; j++) {if (j === 1) {console.log(` 跳过j=${j},直接进入i的下一次迭代`);continue outerLoop;}console.log(` i=${i}, j=${j}`);}
}
输出结果:
示例2输出:
开始i=0的迭代
i=0, j=0
跳过j=1,直接进入i的下一次迭代
开始i=1的迭代
i=1, j=0
跳过j=1,直接进入i的下一次迭代
开始i=2的迭代
i=2, j=0
跳过j=1,直接进入i的下一次迭代
注意每次j=1时,内层循环的剩余迭代(j=2)都被跳过了。
2.同步请求阻塞主线程
在看到js的XMLHttpRequest的实例方法open()时,看到了这么一句话,主线程上的同步请求很容易破坏用户体验,应该避免;实际上,许多浏览器已完全弃用主线程上的同步 XHR 支持。 想了想,同步异步不都是等待接口返回再进行赋值等的操作吗,区别在哪里呢。
首先,我需要回忆JavaScript的单线程特性。主线程负责执行代码、处理DOM、响应事件等。如果主线程被长时间的任务阻塞,页面就会卡顿,用户操作无法及时响应,导致糟糕的用户体验。而同步请求,比如同步的XMLHttpRequest,会阻塞主线程,直到请求完成,这期间所有其他操作都会被挂起。
举个例子:
<template><div class="demo"><h2>请求阻塞示例</h2><div class="counter"><p>计数器: {{ counter }}</p><button @click="startCounter">开始计数</button></div><div class="section"><h3>❌ 同步请求(会阻塞计数)</h3><button @click="makeSyncXHR">同步请求</button><p>状态: {{ syncXHRStatus }}</p><p class="note">注意:点击后计数器会停止,直到请求完成</p></div><div class="section"><h3>✅ 异步请求(不会阻塞计数)</h3><button @click="makeAsyncXHR">异步请求</button><p>状态: {{ asyncXHRStatus }}</p><p class="note">注意:点击后计数器会继续运行</p></div><div class="section"><h3>✅ Fetch 请求(不会阻塞计数)</h3><button @click="makeFetchRequest">Fetch 请求</button><p>状态: {{ fetchStatus }}</p><p class="note">注意:点击后计数器会继续运行</p></div></div>
</template><script>export default {name: 'Demo',data() {return {counter: 0,counterInterval: null,syncXHRStatus: '未开始',asyncXHRStatus: '未开始',fetchStatus: '未开始',}},methods: {startCounter() {if (this.counterInterval) {clearInterval(this.counterInterval)}this.counter = 0this.counterInterval = setInterval(() => {this.counter++}, 100)},// 不推荐:同步 XHR 请求makeSyncXHR() {this.syncXHRStatus = '请求中...'const xhr = new XMLHttpRequest()xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1', false) // false 表示同步try {xhr.send() // 这行代码会阻塞主线程this.syncXHRStatus = '请求成功'} catch (error) {this.syncXHRStatus = '请求失败'}},// 推荐:异步 XHR 请求makeAsyncXHR() {this.asyncXHRStatus = '请求中...'const xhr = new XMLHttpRequest()xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1', true) // true 表示异步xhr.onload = () => {if (xhr.status === 200) {this.asyncXHRStatus = '请求成功'} else {this.asyncXHRStatus = '请求失败'}}xhr.onerror = () => {this.asyncXHRStatus = '请求失败'}xhr.send() // 这行代码不会阻塞主线程},// 推荐:使用 fetch APImakeFetchRequest() {this.fetchStatus = '请求中...'fetch('https://jsonplaceholder.typicode.com/posts/1').then(response => {if (response.ok) {this.fetchStatus = '请求成功'} else {this.fetchStatus = '请求失败'}}).catch(() => {this.fetchStatus = '请求失败'})},},beforeDestroy() {if (this.counterInterval) {clearInterval(this.counterInterval)}},}
</script><style scoped>.demo {padding: 20px;}.counter {margin-bottom: 20px;padding: 15px;background-color: #f5f5f5;border-radius: 4px;}.section {margin-bottom: 20px;padding: 15px;border: 1px solid #eee;border-radius: 4px;}button {padding: 8px 16px;margin-right: 10px;background-color: #4caf50;color: white;border: none;border-radius: 4px;cursor: pointer;}button:hover {background-color: #45a049;}.note {color: #666;font-size: 0.9em;margin-top: 5px;}
</style>
效果:
可以看到用了同步的XMLHttpRequest,会阻塞主线程,定时器都要等下来,等接口返回接口后,才会继续渲染页面。