axios#Canceler TypeScript Examples

The following examples show how to use axios#Canceler. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Uploader.ts    From electron with MIT License 6 votes vote down vote up
constructor(file: UploadFileTypes, options?: AxiosRequestConfig) {
    this.file = file;
    this.DefaultOptions = {
      method: 'post',
      /** 默认上报地址 */
      url: '/upload',
      cancelToken: new axiosSource.CancelToken((cancel) => (this.Canceler = cancel)),
      headers: { 'Content-Type': 'multipart/form-data' },
      onUploadProgress: (progressEvent: ProgressEvent) => {
        this._onProgress && this._onProgress(this.transformData(progressEvent));
      },
      ...(options ?? {})
    };
  }
Example #2
Source File: useFetchData.tsx    From cards-against-formality-pwa with BSD 2-Clause "Simplified" License 5 votes vote down vote up
/**
 *
 *
 * @param {string} uri
 * @param {FetchType} [type=FetchType.GET]
 * @param {AxiosRequestConfig} [options]
 * @returns {([T, boolean, string | null, (body: any, noRedirect?: boolean) => void, () => void])}
 */
function useFetchData<T>(
  uri: string,
  type: FetchType = FetchType.GET,
  options: AxiosRequestConfig = defaultOption,
  interval?: number
): [T | null, boolean, string | null, (body?: any, noRedirect?: boolean) => Promise<any>, () => void] {

  const { baseUrl } = useContext(ConfigContext);
  const { history } = useContext(RouterContext);
  const historyRef = useRef(history);

  const [data, setData] = useState<T | null>(null);
  const [isLoading, setLoading] = useState(false);
  const [errorMessage, setErrorMessage] = useState(null);
  const cancelToken = useRef<Canceler | null>(null);

  const next = useCallback(_next, [baseUrl, uri, type, options]);

  useEffect(() => {
    historyRef.current = history;
  }, [history]);

  useEffect(() => {
    if (type === FetchType.GET) {
      next().catch(() => { });
    }
  }, [type, next, interval])

  function cancel() {
    if (cancelToken.current) {
      cancelToken.current();
    }
  }

  function _next(body?: any, noRedirect?: boolean) {
    if (cancelToken.current) {
      cancel();
    }
    const currentUser = firebase.auth().currentUser;
    if (!currentUser) {
      return Promise.reject(new Error('No user.'));
    }

    setLoading(true);
    const _options = Object.assign({}, options, { cancelToken: new axios.CancelToken(token => cancelToken.current = token) });
    return currentUser.getIdToken()
      .then(token => {
        if (token?.length) {
          axios.defaults.headers['Authorization'] = `Bearer ${token}`;
        }
        return constructRequest(`${baseUrl}${uri}`, type, _options, body)
      })
      .then(res => {
        setLoading(false);
        setErrorMessage(null);
        setData(res.data);
        return res;
      })
      .catch(err => {
        setLoading(false);
        if (!noRedirect && (err.code === 401 || err.response?.status === 401)) {
          historyRef.current.push('/login');
          throw err;
        }

        setErrorMessage(err.response?.data ? err.response.data.message : 'Something went wrong.')
        throw err;
      });
  }

  return [data, isLoading, errorMessage, next, cancel];
}
Example #3
Source File: datasource.ts    From querybook with Apache License 2.0 5 votes vote down vote up
function syncDatasource<T>(
    method: Method,
    urlOrOptions: UrlOrOptions,
    data?: Record<string, unknown>,
    notifyOnError?: boolean
): ICancelablePromise<{ data: T }> {
    const url =
        typeof urlOrOptions === 'string' ? urlOrOptions : urlOrOptions['url'];

    let cancel: Canceler;
    const defaultConfig: AxiosRequestConfig = {
        url,
        baseURL: '/ds',
        headers: {
            'Content-Type': 'application/json; charset=utf-8',
        },
        method,
        cancelToken: new axios.CancelToken((c) => (cancel = c)),
    };

    if (data) {
        if (method === 'GET') {
            defaultConfig.params = {
                params: data,
            };
        } else {
            defaultConfig.data = data;
        }
    }

    const combinedConfig =
        typeof urlOrOptions === 'string'
            ? defaultConfig
            : {
                  ...defaultConfig,
                  ...urlOrOptions,
              };

    const request: ICancelablePromise<any> = axios.request(combinedConfig).then(
        (resp) => {
            if (resp.status === 200) {
                return Promise.resolve(resp.data);
            } else {
                return handleRequestException(resp, notifyOnError);
            }
        },
        (rej) => handleRequestException(rej, notifyOnError)
    );

    request.cancel = cancel;

    return request;
}
Example #4
Source File: Uploader.ts    From electron with MIT License 5 votes vote down vote up
cancel(message?: string): void {
    this.Canceler && this.Canceler(message);
    this.Canceler = undefined;
  }
Example #5
Source File: Uploader.ts    From electron with MIT License 5 votes vote down vote up
private Canceler?: Canceler;
Example #6
Source File: TagInput.tsx    From Hybooru with MIT License 4 votes vote down vote up
export default function TagInput({ ...rest }: InputHTMLAttributes<HTMLInputElement>) {
  const [showNamespace] = useLocalStorage("namespaces", false);
  const [tags, setTags] = useState<Record<string, number> | null>(null);
  const inputRef = useRef<HTMLInputElement | null>(null);
  const tagsRef = useRef<HTMLDivElement | null>(null);
  const box = inputRef.current?.getBoundingClientRect();
  const timeoutRef = useRef<NodeJS.Timeout | number | null>(null);
  const blurRef = useRef<NodeJS.Timeout | number | null>(null);
  const requestRef = useRef<Canceler | null>(null);
  
  const [query, setQuery] = useRTQuery();
  const queryRef = useRef(query);
  queryRef.current = query;
  
  const stop = useCallback(() => {
    if(timeoutRef.current) {
      clearTimeout(timeoutRef.current as any);
      timeoutRef.current = null;
    }
    if(requestRef.current) {
      requestRef.current();
      requestRef.current = null;
    }
  }, []);
  
  const reset = useCallback(() => {
    stop();
    
    timeoutRef.current = setTimeout(async () => {
      timeoutRef.current = null;
      
      let query = queryRef.current.split(" ").slice(-1)[0];
      if(query.startsWith("-")) query = query.slice(1);
      query = `*${query}*`;
      
      const result = await requestJSON<TagsSearchResponse, TagsSearchRequest>({
        pathname: "/api/tags",
        search: {
          pageSize: TAGS_COUNT,
          query,
        },
        cancelCb: cancel => requestRef.current = cancel,
      });
      
      setTags(result.tags);
    }, DEBOUNCE_FREQ);
  }, [stop]);
  
  const onFocus = useCallback(() => {
    reset();
    if(blurRef.current) clearTimeout(blurRef.current as any);
  }, [reset]);
  
  const onBlur = useCallback(() => {
    blurRef.current = setTimeout(() => {
      blurRef.current = null;
      setTags(null);
      stop();
    }, 100);
  }, [stop]);
  
  const onInputChange = useCallback((ev: React.ChangeEvent<HTMLInputElement>) => {
    reset();
    setQuery(ev.target.value, true);
  }, [reset, setQuery]);
  
  const onRowClick = useCallback((tag: string) => {
    setQuery(query => {
      inputRef.current?.focus();
      
      const parts = query.split(" ");
      if(parts[parts.length - 1].startsWith("-")) tag = `-${tag}`;
      parts[parts.length - 1] = tag;
      return parts.join(" ") + " ";
    }, true);
  }, [setQuery]);
  
  const onKeyPress = useCallback((ev: React.KeyboardEvent<HTMLInputElement>) => {
    if(ev.key === "Enter") {
      ev.currentTarget.blur();
    }
  }, []);
  
  const onKeyDown = useCallback((ev: React.KeyboardEvent<HTMLInputElement>) => {
    if(ev.key === "ArrowDown" || ev.key === "ArrowUp") {
      ev.preventDefault();
      
      const targets = [inputRef.current, ...Array.from(tagsRef.current?.children || [])] as Array<(null | HTMLAnchorElement | HTMLInputElement)>;
      const cur = targets.indexOf(document.activeElement as any);
      if(cur < 0) return;
      
      const dir = ev.key === "ArrowDown" ? 1 : -1;
      targets[cur + dir]?.focus();
    }
  }, []);
  
  return (
    <span className="TagInput" onFocus={onFocus} onBlur={onBlur} onKeyDown={onKeyDown}>
      <input value={query} {...rest} ref={inputRef}
             autoComplete="off" autoCorrect="off"
             onChange={onInputChange} onKeyPress={onKeyPress} />
      {tags && box &&
        <div className="tags" ref={tagsRef}
             style={{
               left: `${box.x - 1}px`,
               top: `${box.y + box.height - 1}px`,
               width: `${box.width + 2}px`,
             }}>
          {Object.entries(tags).map(([tag, posts]) => <Row key={tag} tag={tag} posts={posts} onClick={onRowClick} showNamespace={showNamespace} />)}
        </div>
      }
    </span>
  );
}
Example #7
Source File: usePostsCache.tsx    From Hybooru with MIT License 4 votes vote down vote up
export default function usePostsCache() {
  const location = useLocation();
  const history = useHistory();
  const canceller = useRef<Canceler | null>(null);
  const [fetching, setFetching] = useState(false);
  const postsCache = useContext(PostsCacheContext);
  const search = qs.parse(location.search);
  const query = typeof search.query === "string" ? search.query : "";
  const key = JSON.stringify([search.page, query]);
  const [pageData, pageFetching] = usePageData<PostsSearchPageData>(!postsCache[key], false);
  
  let postsCacheDefault = emptyPage;
  if(postsCache[key]) {
    postsCacheDefault = postsCache[key];
  } else if(pageData) {
    postsCacheDefault = postsCache[key] = {
      page: 1,
      tags: {},
      ...pageData.results,
    };
  }
  
  const [currentCache, setCurrentCache] = useState<PostsCacheData>(postsCacheDefault);
  
  useEffect(() => {
    if(postsCache[key] && currentCache !== postsCache[key]) {
      setCurrentCache(postsCache[key]);
    }
  }, [currentCache, pageData, postsCache, key]);
  
  useEffect(() => {
    return history.listen(() => {
      if(canceller.current) canceller.current();
      canceller.current = null;
    });
  }, [history]);
  
  const requestNext = useCallback(async () => {
    if(canceller.current || pageFetching || !postsCache[key]) return;
    
    try {
      if(postsCache[key].total !== null && postsCache[key].posts.length >= (postsCache[key].total || 0)) return;
      
      setFetching(true);
      const result = await requestJSON<PostsSearchResponse, PostsSearchRequest>({
        pathname: "/api/post",
        search: {
          query,
          page: postsCache[key].page,
        },
        cancelCb: cancel => canceller.current = cancel,
      });
      
      postsCache[key] = {
        ...postsCache[key],
        page: postsCache[key].page + 1,
        posts: [...postsCache[key].posts, ...result.posts],
        total: result.posts.length === 0 ? postsCache[key].posts.length : postsCache[key].total,
      };
      
      setCurrentCache(postsCache[key]);
    } catch(e) {
      if(!(e instanceof axios.Cancel)) throw e;
    } finally {
      canceller.current = null;
      setFetching(false);
    }
  }, [pageFetching, postsCache, key, query]);
  
  const reset = useCallback(() => {
    if(pageData) {
      postsCache[key] = {
        page: 1,
        tags: {},
        ...pageData.results,
      };
    } else {
      postsCache[key] = emptyPage;
    }
    setCurrentCache(postsCache[key]);
  }, [key, pageData, postsCache]);
  
  return { postsCache: currentCache, fetching, requestNext, reset } as const;
}