на форме фильтр + грид
данные с бэка забираю через fetch
полученными данными обновляется грид
запрос довольно тяжелый / долгий
проблема возникает когда пользователь генерит новый запрос до завершения предыдущего
контент в гриде обновляется несколько раз
можно как то прервать / отказаться от "устаревшего" запроса?
P.S. обертывание fetch в clearTimeout / setTimeout в данной ситуации не спасает
P.S.S. или както проверять является ли полученный данные результатом последнего promis'а?
UPDATE
страница на ReactJS
публикация кода ничего не даст, т.к. проблема общего плана
ситуация в том, что нет кнопки "НАЙТИ", запрос генерится при каждом "чихе" в фильтре
фильтр огромный из 10ков полей и выпадающих списков
дисейблить его при каждом запросе не получится по идеалогическим соображениям клиента
вижу единственный вариант это отказываться или игнорировать устаревшие запросы
но хотел поискать BEST PRACTICES
UPDATE2
class View extends Component {
...
updateItems(data) {
self.state.timeoutItems && clearTimeout(self.state.timeoutItems);
self.state.timeoutItems = setTimeout(() => {
self.props.onGetItems(self.calcParams());
}, config.timeoutItems );
}
}
export default connect(
state => ({
items: state.items
}),
dispatch => ({
onGetItems: (o) => {
dispatch(getItems(o));
}
})
)(View);
...
export const getItems = (o = {}) => dispatch => {
...
fetch(url, {
method: 'GET',
headers: {
"Content-type": "application/json",
"Accept": "application/json"
},
})
.then( (response) => response.json() )
.then((data) => {
==>> (1) <<==
dispatch({ type: 'FETCH_ITEMS_SUCCESS', data: data });
})
.catch((error) => {
console.log('Request failed', error);
});
}
можно ли в точке (1) определить к какому promise относится полученный результат?
На текущее время нативно отменить fetch
нельзя, это потому что он использует механизм Promise
-ов, в которых тоже нет механизма прерывания. Поэтому приходится ухитряться и писать костыли
Есть библиотека axios, тоже использует Promise
, правда работает вроде все еще на стандартном XMLHttpRequest
, но возможность отмены там есть:
var CancelToken = axios.CancelToken;
var source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// handle error
}
});
// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');
Если хотите использовать нативный fetch
придется пока писать свою реализацию отмены запроса (да и то, это не будет настоящей отменой запроса, потому что ответ все равно придет, просто вы его проигнорируете)
UPD
Дискасс на эту тему
Способа отменить fetch
нет и вроде как не предвидится.
Выбрать наиболее новый и отрисовать именно его можно как-то так:
let counter = 0; // Флаг итератора количества запросов
function buildRequest(){
console.info(`Запрос #${counter + 1} послан`);
makeRequest(++counter); // Новый запрос получает более большое число
}
function makeRequest(num){
setTimeout(_ => {
if(counter > num){ // Если итератор больше текущего числа, значит был запрос позже, выходим
console.info(`Запрос #${num} отменён, есть запросы позже`);
return;
}
// Иначе рисуем ответ
console.info(`Запрос #${num} начинает отрисовку`);
}, 1000);
}
buildRequest();
setTimeout(_ => buildRequest(), 500);
setTimeout(_ => buildRequest(), 1000);
Но сервер всё равно будет в поте процессора трудится.
Иначе либо ставьте запросы в очередь, либо сделайте заблокируйте фильтры на момент запроса.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Есть json файл http://jsonplaceholdertypicode
Как сделать так, чтобы гугл карты загружались на сайт после того, как пользователь совершил какие-либо действия(например, проскроллил страницу)...
Не знал как назвать, кто придумает по умнее, буду признателенПроблема в том, что PhpStorm не подчеркнул и я упустил из виду: