Created
May 14, 2019 14:09
-
-
Save ipetropolsky/d6da3230551dacd56efde6b51003c74c to your computer and use it in GitHub Desktop.
Fetcher with canceling requests by groups and tags
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import axios, { CancelToken, isCancel } from 'axios'; | |
const instance = axios.create({ | |
withCredentials: true, | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
}, | |
}); | |
let nextRequestId = 0; | |
function shouldCancel(oldRequest, newRequest) { | |
return oldRequest.cancelTags.some((tag) => newRequest.cancelTags.includes(tag)); | |
} | |
function CancelGroup() { | |
let requests = []; | |
return { | |
add(newRequest) { | |
requests = requests.filter((oldRequest) => { | |
if (shouldCancel(oldRequest, newRequest)) { | |
oldRequest.cancel(); | |
return false; | |
} | |
return true; | |
}); | |
requests.push(newRequest); | |
}, | |
remove(requestId) { | |
requests = requests.filter((request) => { | |
return request.requestId !== requestId; | |
}); | |
}, | |
filter(filter) { | |
requests = requests.filter(filter); | |
}, | |
}; | |
} | |
/** | |
* Хранилище отменяемых запросов. | |
* | |
* Если делается запрос с `cancelGroup` и `cancelTags`, отменяются запросы | |
* с такой же группой и совпадением одного из тегов. Нужно для тонкой настройки | |
* отмены, например, когда запрос на редактирование отменяет только другие запросы | |
* на редактирование, а запрос на удаление отменяет и редактирование, и удаление. | |
* Группа ограничивает область отмены, например, если редактирование одного ID | |
* не должно отменять редактирование другого, делаются запросы с разными группами. | |
* | |
* @type {{ cancelGroup: [ { requestId, cancelTags[], cancel() } ] }} | |
*/ | |
const cancelGroups = {}; | |
instance.interceptors.request.use( | |
(config) => { | |
const requestId = nextRequestId; | |
const { cancelGroup, cancelTags } = config; | |
if (cancelGroup && cancelTags && cancelTags.length) { | |
const source = CancelToken.source(); | |
config.cancelToken = source.token; | |
cancelGroups[cancelGroup] = cancelGroups[cancelGroup] || new CancelGroup(); | |
cancelGroups[cancelGroup].add({ requestId, cancelTags, cancel: source.cancel }); | |
} | |
config.requestId = requestId; | |
nextRequestId += 1; | |
return config; | |
}, | |
(error) => { | |
return Promise.reject(error); | |
} | |
); | |
instance.interceptors.response.use( | |
(response) => { | |
const { requestId, cancelGroup } = response.config; | |
if (cancelGroup && cancelGroups[cancelGroup]) { | |
cancelGroups[cancelGroup].remove(requestId); | |
} | |
return response; | |
}, | |
(error) => { | |
error.isCancel = isCancel(error); | |
return Promise.reject(error); | |
} | |
); | |
export default instance; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import fetcher from './fetcher'; | |
// ... | |
// save | |
fetcher.post('/url', data, { | |
cancelGroup: internalId, | |
cancelTags: ['automoderation', 'save'], | |
}); | |
// delete | |
fetcher.delete('/url', { | |
cancelGroup: internalId, | |
cancelTags: ['save', 'automoderation', 'delete'], | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment