axios 중복 쓸모없는 요청 을 취소 하 는 방법

머리말
개발 에 서 는 인터페이스 중복 요청 으로 인 한 여러 가지 문제 가 자주 발생 한다.
중복 되 는 get 요청 은 페이지 를 여러 번 업데이트 하고 페이지 디 더 링 현상 이 발생 하여 사용자 체험 에 영향 을 줄 수 있 습 니 다.
중복 되 는 post 요청 에 대해 서 는 서버 에서 두 번 의 기록 을 생 성 할 수 있 습 니 다(예 를 들 어 두 개의 주문 기록 생 성).
현재 페이지 요청 이 완료 되 지 않 았 다 면 다음 경로 로 전환 되 었 습 니 다.이 요청 들 은 응답 이 돌아 올 때 까지 중단 되 었 습 니 다.
사용자 체험 이나 업무 엄밀 측면 에서 볼 때 쓸모없는 요 구 를 취소 하 는 것 은 확실히 피해 야 한다.
물론 저 희 는 페이지 loading 을 통 해 사용자 가 다음 작업 을 하 는 것 을 피 할 수 있 지만 본 고 는 이러한 쓸모없는 요 구 를 어떻게 취소 하 는 지 에 대해 서 만 논의 하고 있 습 니 다.
axios 의 cancelToken
axios 는 주류 http 요청 라 이브 러 리 로 요청 을 취소 하 는 두 가지 방식 을 제공 합 니 다.
axios.Cancel Token.source 를 통 해 취소 토 큰 생 성 및 취소 방법 cancel

const CancelToken = axios.CancelToken;
const 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
 }
});

axios.post('/user/12345', {
 name: 'new name'
}, {
 cancelToken: source.token
})

// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');
axios.Cancel Token 구조 함수 생 성 취소 함수

const CancelToken = axios.CancelToken;
let cancel;

axios.get('/user/12345', {
 cancelToken: new CancelToken(function executor(c) {
 // An executor function receives a cancel function as a parameter
 cancel = c;
 })
});

// cancel the request
cancel();
주의해 야 할 것 은 catch 에서 이상 을 포착 할 때 axios.isCancel()을 사용 하여 현재 요청 이 주동 적 으로 취소 되 었 는 지 판단 하여 일반적인 이상 논 리 를 구분 해 야 합 니 다.
패키지 취소 요청 논리
위 에 두 가지 취소 요청 이 있 습 니 다.어떤 것 을 사용 하 든 좋 습 니 다.여 기 는 두 번 째 것 을 사용 합 니 다.
취소 요청 은 주로 두 장면 이 있 습 니 다:
  • 요청 방식 method,요청 경로 url,요청 매개 변수(get 은 params,post 는 data)가 모두 같 을 때 같은 요청 으로 여러 번 보 낸 것 으로 볼 수 있 습 니 다.이전 요청 을 취소 해 야 합 니 다
  • 경로 전환 시 이전 경로 에서 완료 되 지 않 은 요청 을 취소 해 야 합 니 다
  • 우 리 는 몇 가지 방법 을 봉인 한다.
    
    //      Map                   
    const pending = new Map()
    /**
     *     
     * @param {Object} config 
     */
    const addPending = (config) => {
     const url = [
     config.method,
     config.url,
     qs.stringify(config.params),
     qs.stringify(config.data)
     ].join('&')
     config.cancelToken = config.cancelToken || new axios.CancelToken(cancel => {
     if (!pending.has(url)) { //    pending         ,     
      pending.set(url, cancel)
     }
     })
    }
    /**
     *     
     * @param {Object} config 
     */
    const removePending = (config) => {
     const url = [
     config.method,
     config.url,
     qs.stringify(config.params),
     qs.stringify(config.data)
     ].join('&')
     if (pending.has(url)) { //     pending          ,        ,    
     const cancel = pending.get(url)
     cancel(url)
     pending.delete(url)
     }
    }
    /**
     *    pending     (        )
     */
    export const clearPending = () => {
     for (const [url, cancel] of pending) {
     cancel(url)
     }
     pending.clear()
    }
    Map 은 ES6 에서 새로운 데이터 구조 로 그 자체 가 여러 가지 방법 을 제공 하여 조작 하기에 편리 하고 현재 장면 에 적합 합 니 다.익숙 하지 않 은 것 은 볼 수 있다ECMAScript 6 입문
    config.cancelToken 에 값 을 부여 할 때 현재 요청 이 업무 코드 에 cancelToken 을 사 용 했 는 지 판단 해 야 합 니 다.
    qs 는 대상 과 문자열 파 라 메 터 를 변환 하 는 라 이브 러 리 입 니 다.처음에는 TJ 가 만 들 고 유지 하 는 것 이 었 으 며,axios 가 추천 하 는 매개 변수 직렬 화 라 이브 러 리 였 습 니 다.여기 서 우리 의 목적 은 단순히 매개 변수 대상 을 문자열 로 바 꾸 어 쉽게 연결 하 는 것 입 니 다.
    Map 구 조 는 기본적으로 Symbol.iterator 속성 을 배 치 했 습 니 다.for...of 순환 을 사용 하여 키 이름과 키 값 을 직접 가 져 올 수 있 습 니 다.물론 for...in 순환 도 사용 할 수 있 습 니 다.
    axios 차단기 에서 사용 하기
    주요 방법 은 이미 다 썼 으 니 axios 차단기 에 추가 하면 된다.
    
    axios.interceptors.request.use(config => {
     removePending(options) //       ,             
     addPending(options) //          pending  
     // other code before request
     return config
    }, error => {
     return Promise.reject(error)
    })
    
    axios.interceptors.response.use(response => {
     removePending(response) //       ,      
     return response
    }, error => {
     if (axios.isCancel(error)) {
     console.log('repeated request: ' + error.message)
     } else {
     // handle error code
     }
     return Promise.reject(error)
    })
    vue 경로 갈고리 함수 에 clearPending()방법 을 추가 합 니 다.
    
    router.beforeEach((to, from, next) => {
     clearPending()
     // ...
     next()
    })
    테스트 효과
    마지막 으로 저 희 는 브 라 우 저 에서 chrome 에서 패 널 을 제어 하 는 Network 의 네트워크 상 태 를 Slow 3G 로 전환 하여 네트워크 속도 가 느 린 상황 을 모 의 할 수 있 습 니 다.
    우 리 는 검색 단추 의 loading 이나 disabled 속성 을 제거 하여 테스트 를 편리 하 게 합 니 다.

    위 제어 판 에서 볼 수 있 듯 이 빨간색 status 가 canceled 인 것 은 취 소 된 요청 입 니 다.
    위의 코드 는e-admin-vue(vue+element-ui+vue-cli 3 로 구 축 된 rbac 권한 모델)또는e-admin-react(react+antd+create-react-app 로 구 축 된 rbac 권한 모델)에 모두 나타 나 있 습 니 다.스타 를 환영 합 니 다.
    총결산
    이상 은 이 글 의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가 치 를 가지 기 를 바 랍 니 다.여러분 의 저희 에 대한 지지 에 감 사 드 립 니 다.

    좋은 웹페이지 즐겨찾기