日常开发记录
1.for循环的打断特定循环
看到了一段这个代码,第一次见
在 JavaScript 中,当我们需要从嵌套循环中跳出时,普通的 break 语句只能跳出当前循环。而标签语法(Labeled Statements)提供了一种更灵活的方式,允许我们从多层嵌套的循环中直接跳出。
示例1:跳出嵌套循环
javascript
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跳到外层循环
javascript
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,会阻塞主线程,直到请求完成,这期间所有其他操作都会被挂起。
举个例子:
javascript
<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 = 0
this.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 API
makeFetchRequest() {
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,会阻塞主线程,定时器都要等下来,等接口返回接口后,才会继续渲染页面。