Replace CancelToken to AbortSignal (#19352)

This commit is contained in:
Yamagishi Kazutoshi 2022-10-14 10:16:37 +09:00 committed by GitHub
parent f01310dadb
commit 219c38b921
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 93 additions and 38 deletions

View File

@ -1,18 +1,20 @@
import api from '../api'; import { isCancel } from 'axios';
import { CancelToken, isCancel } from 'axios';
import { throttle } from 'lodash'; import { throttle } from 'lodash';
import { search as emojiSearch } from '../features/emoji/emoji_mart_search_light';
import { tagHistory } from '../settings';
import { useEmoji } from './emojis';
import resizeImage from '../utils/resize_image';
import { importFetchedAccounts } from './importer';
import { updateTimeline } from './timelines';
import { showAlertForError } from './alerts';
import { showAlert } from './alerts';
import { openModal } from './modal';
import { defineMessages } from 'react-intl'; import { defineMessages } from 'react-intl';
import api from 'mastodon/api';
import { search as emojiSearch } from 'mastodon/features/emoji/emoji_mart_search_light';
import { tagHistory } from 'mastodon/settings';
import resizeImage from 'mastodon/utils/resize_image';
import { showAlert, showAlertForError } from './alerts';
import { useEmoji } from './emojis';
import { importFetchedAccounts } from './importer';
import { openModal } from './modal';
import { updateTimeline } from './timelines';
let cancelFetchComposeSuggestionsAccounts, cancelFetchComposeSuggestionsTags; /** @type {AbortController | undefined} */
let fetchComposeSuggestionsAccountsController;
/** @type {AbortController | undefined} */
let fetchComposeSuggestionsTagsController;
export const COMPOSE_CHANGE = 'COMPOSE_CHANGE'; export const COMPOSE_CHANGE = 'COMPOSE_CHANGE';
export const COMPOSE_SUBMIT_REQUEST = 'COMPOSE_SUBMIT_REQUEST'; export const COMPOSE_SUBMIT_REQUEST = 'COMPOSE_SUBMIT_REQUEST';
@ -433,8 +435,8 @@ export function undoUploadCompose(media_id) {
}; };
export function clearComposeSuggestions() { export function clearComposeSuggestions() {
if (cancelFetchComposeSuggestionsAccounts) { if (fetchComposeSuggestionsAccountsController) {
cancelFetchComposeSuggestionsAccounts(); fetchComposeSuggestionsAccountsController.abort();
} }
return { return {
type: COMPOSE_SUGGESTIONS_CLEAR, type: COMPOSE_SUGGESTIONS_CLEAR,
@ -442,14 +444,14 @@ export function clearComposeSuggestions() {
}; };
const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) => { const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) => {
if (cancelFetchComposeSuggestionsAccounts) { if (fetchComposeSuggestionsAccountsController) {
cancelFetchComposeSuggestionsAccounts(); fetchComposeSuggestionsAccountsController.abort();
} }
fetchComposeSuggestionsAccountsController = new AbortController();
api(getState).get('/api/v1/accounts/search', { api(getState).get('/api/v1/accounts/search', {
cancelToken: new CancelToken(cancel => { signal: fetchComposeSuggestionsAccountsController.signal,
cancelFetchComposeSuggestionsAccounts = cancel;
}),
params: { params: {
q: token.slice(1), q: token.slice(1),
@ -472,16 +474,16 @@ const fetchComposeSuggestionsEmojis = (dispatch, getState, token) => {
}; };
const fetchComposeSuggestionsTags = throttle((dispatch, getState, token) => { const fetchComposeSuggestionsTags = throttle((dispatch, getState, token) => {
if (cancelFetchComposeSuggestionsTags) { if (fetchComposeSuggestionsTagsController) {
cancelFetchComposeSuggestionsTags(); fetchComposeSuggestionsTagsController.abort();
} }
dispatch(updateSuggestionTags(token)); dispatch(updateSuggestionTags(token));
fetchComposeSuggestionsTagsController = new AbortController();
api(getState).get('/api/v2/search', { api(getState).get('/api/v2/search', {
cancelToken: new CancelToken(cancel => { signal: fetchComposeSuggestionsTagsController.signal,
cancelFetchComposeSuggestionsTags = cancel;
}),
params: { params: {
type: 'hashtags', type: 'hashtags',

View File

@ -1,20 +1,31 @@
// @ts-check
import axios from 'axios'; import axios from 'axios';
import LinkHeader from 'http-link-header'; import LinkHeader from 'http-link-header';
import ready from './ready'; import ready from './ready';
/**
* @param {import('axios').AxiosResponse} response
* @returns {LinkHeader}
*/
export const getLinks = response => { export const getLinks = response => {
const value = response.headers.link; const value = response.headers.link;
if (!value) { if (!value) {
return { refs: [] }; return new LinkHeader();
} }
return LinkHeader.parse(value); return LinkHeader.parse(value);
}; };
/** @type {import('axios').RawAxiosRequestHeaders} */
const csrfHeader = {}; const csrfHeader = {};
/**
* @returns {void}
*/
const setCSRFHeader = () => { const setCSRFHeader = () => {
/** @type {HTMLMetaElement | null} */
const csrfToken = document.querySelector('meta[name=csrf-token]'); const csrfToken = document.querySelector('meta[name=csrf-token]');
if (csrfToken) { if (csrfToken) {
@ -24,6 +35,10 @@ const setCSRFHeader = () => {
ready(setCSRFHeader); ready(setCSRFHeader);
/**
* @param {() => import('immutable').Map} getState
* @returns {import('axios').RawAxiosRequestHeaders}
*/
const authorizationHeaderFromState = getState => { const authorizationHeaderFromState = getState => {
const accessToken = getState && getState().getIn(['meta', 'access_token'], ''); const accessToken = getState && getState().getIn(['meta', 'access_token'], '');
@ -36,17 +51,25 @@ const authorizationHeaderFromState = getState => {
}; };
}; };
export default getState => axios.create({ /**
* @param {() => import('immutable').Map} getState
* @returns {import('axios').AxiosInstance}
*/
export default function api(getState) {
return axios.create({
headers: { headers: {
...csrfHeader, ...csrfHeader,
...authorizationHeaderFromState(getState), ...authorizationHeaderFromState(getState),
}, },
transformResponse: [function (data) { transformResponse: [
function (data) {
try { try {
return JSON.parse(data); return JSON.parse(data);
} catch(Exception) { } catch {
return data; return data;
} }
}], },
],
}); });
}

View File

@ -1,3 +1,4 @@
import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only';
import 'intersection-observer'; import 'intersection-observer';
import 'requestidlecallback'; import 'requestidlecallback';
import objectFitImages from 'object-fit-images'; import objectFitImages from 'object-fit-images';

View File

@ -26,6 +26,7 @@ function loadPolyfills() {
// Edge does not have requestIdleCallback and object-fit CSS property. // Edge does not have requestIdleCallback and object-fit CSS property.
// This avoids shipping them all the polyfills. // This avoids shipping them all the polyfills.
const needsExtraPolyfills = !( const needsExtraPolyfills = !(
window.AbortController &&
window.IntersectionObserver && window.IntersectionObserver &&
window.IntersectionObserverEntry && window.IntersectionObserverEntry &&
'isIntersecting' in IntersectionObserverEntry.prototype && 'isIntersecting' in IntersectionObserverEntry.prototype &&

22
jsconfig.json Normal file
View File

@ -0,0 +1,22 @@
{
"compilerOptions": {
"allowJs": true,
"baseUrl": "./app/javascript",
"checkJs": false,
"experimentalDecorators": true,
"jsx": "react",
"lib": ["DOM", "DOM.Iterable", "ES2022"],
"module": "ES2022",
"moduleResolution": "node",
"noEmit": true,
"resolveJsonModule": true,
"strict": false,
"target": "ES2022"
},
"exclude": [
"**/build/*",
"**/node_modules/*",
"**/public/*",
"**/vendor/*"
]
}

View File

@ -34,6 +34,7 @@
"@gamestdio/websocket": "^0.3.2", "@gamestdio/websocket": "^0.3.2",
"@github/webauthn-json": "^0.5.7", "@github/webauthn-json": "^0.5.7",
"@rails/ujs": "^6.1.7", "@rails/ujs": "^6.1.7",
"abortcontroller-polyfill": "^1.7.5",
"array-includes": "^3.1.5", "array-includes": "^3.1.5",
"arrow-key-navigation": "^1.2.0", "arrow-key-navigation": "^1.2.0",
"autoprefixer": "^9.8.8", "autoprefixer": "^9.8.8",

View File

@ -2203,6 +2203,11 @@ abab@^2.0.6:
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==
abortcontroller-polyfill@^1.7.5:
version "1.7.5"
resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed"
integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8:
version "1.3.8" version "1.3.8"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"