展示
点击下面每一个按钮都会请求,请求时间在0.5s-1.5s之间随机,快速点击,看看返回的数据是哪一个?
代码
CSS代码:
.container {
max-width: 600px;
margin-inline: auto;
}
.operate {
display: flex;
gap: .5rem;
}
.operate button {
flex: 1;
font-size: 100%;
height: 2.5rem;
}
.result {
display: grid;
border: 1px solid #ddd;
background-color: #f5f5f5;
margin-block: 1rem;
padding: 1.5rem;
place-items: center;
}
.result:empty::before {
content: '结果返回区域';
color: darkgray;
}
.result.loading {
font-size: 0;
}
.result.loading::before {
content: '';
border: 2px solid deepskyblue;
border-top-color: transparent;
border-radius: 50%;
animation: spin 1s linear infinite;
width: 1.5rem; height: 1.5rem;
box-sizing: border-box;
}
@keyframes spin {
from { transform: rotate(0); }
to { transform: rotate(360deg); }
}
.error {
color: red;
}
HTML代码:
<div class="container">
<p>点击下面每一个按钮都会请求,请求时间在0.5s-1.5s之间随机,快速点击,看看返回的数据是哪一个?</p>
<div id="operate" class="operate">
<button value="zhang">返回“zhang”</button>
<button value="xin">返回“xin”</button>
<button value="xu">返回“xu”</button>
</div>
<div id="result" class="result"></div>
</div>
JS代码:
const data = {};
// 对象和视图关联
Object.defineProperty(data, 'loading', {
get: function () {
return result.classList.contains('loading');
},
set: function (val) {
result.classList[val ? 'add' : 'remove']('loading');
}
})
// 构造器对象
let conrtoller = null;
// 按钮点击
operate.addEventListener('click', function (event) {
if (event.target.matches('button')) {
// 构造 AbortController 对象
if (data.conrtoller) {
conrtoller = data.conrtoller;
} else {
conrtoller = new AbortController();
data.conrtoller = conrtoller;
}
// 如果正在请求,终止
if (data.loading) {
conrtoller.abort();
// 构建新的 AbortController
conrtoller = new AbortController();
data.conrtoller = conrtoller;
}
data.loading = true;
// 请求逻辑
fetch('./getVal.php?val=' + event.target.value, {
signal: conrtoller.signal
}).then(res => res.text()).then(text => {
data.loading = false;
delete data.conrtoller;
// 显示内容
result.innerHTML = text;
}).catch(error => {
// 显示出错提示
if (!/cancel|abort/i.test(error)) {
delete data.conrtoller;
data.loading = false;
result.innerHTML = '<span class="error">' + error + '</span>';
}
});
}
});