展示
点击下面每一个按钮都会请求,请求时间在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>'; } }); } });