const {useEffect, useState} = React;
const root = ReactDOM.createRoot(
document.getElementById('app')
);
// 创建一个实现竞态的函数,对于多次发送的请求,永远维持最新的请求的响应
function generateStateFunction(fn) {
let requestId = 0;
return function() {
requestId ++;
let pendingRequest = fn.apply(this, arguments);
return new Promise(function(resolve, reject) {
pendingRequest.then(
// 事实上,关于竞态,不管请求返回的早与晚,都只会触发resolve,除非网络中断
constructParamsCacheFunction(resolve, requestId),
constructParamsCacheFunction(reject, requestId)
)
});
function constructParamsCacheFunction(resolve_or_reject_handle, request_index) {
return function() {
/**
* 这里用来判断是否处于竞态
* request_index是指当发出该强请求时,该请求的顺位
* 由于闭包,各个请求共享一个requestId,但是由于再次返回闭包
* request_index被保存,用于和全局的requestId比较
* 若request_index小于requestId则说明这个请求的相应不是最新请求的响应
*/
if (request_index === requestId) {
resolve_or_reject_handle.apply(this, arguments);
}
}
}
}
}
function debounce(fn, delay) {
let timer = null;
return function() {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, arguments), delay);
}
}
function RequestInputBox () {
const [items, setItems] = useState([]);
let latestContent = "";
const onInputChange = debounce((e) => {
const searchContent = e.target.value;
console.log(searchContent);
if (searchContent === "" || searchContent === latestContent) {
return;
}
async function fetchData() {
const response = await fetch(`https://en.wikipedia.org/w/api.php?format=json&action=opensearch&search=${searchContent}&callback=JSON_CALLBACK&origin=*`, {
method: "GET"
});
let origin_data = await response.text();
let data = JSON.parse(origin_data.slice(18, origin_data.length - 1))[1];
return data;
}
let takeLatestRequest = generateStateFunction(fetchData);
takeLatestRequest()
.then(data => setItems(data))
.catch(err => setItems(["network abort!"]));
}, 1000);
return (
<div>
<div>Search what you want!</div>
<input type="text" id="input" onChange={onInputChange}/>
<ul>
{items.map((v) => <li>{v}</li>)}
</ul>
</div>
);
}
root.render(<RequestInputBox />);
利用原生JS实现实时文本框搜索,并实现防抖和竞态
最新推荐文章于 2022-08-25 20:22:09 发布