fetch 차단기 구현

fetch 차단기 (interceptors) 는 일반적으로 http 요청 을 시작 하기 전이 나 그 후에 요청 을 통일 적 으로 처리 하 는 데 사 용 됩 니 다. 예 를 들 어 token 이 실현 하 는 로그 인 인증 권 (모든 요청 에 token 을 가 져 옵 니 다), 404 응답 을 통일 적 으로 처리 하 는 등 입 니 다.ajax 차단기 에는 많은 ajax 라 이브 러 리 가 구현 되 었 습 니 다. 예 를 들 어 jq 의 $. ajax Setup (), $. ajax Prefilter (), $. ajax Error;axios 의 axios. interceptors. request. use (), axios. interceptors. response. use ();vue - resource 의 Vue. http. interceptors. push () 등등.『 8195 』 fetch 에서 자주 사용 하 는 라 이브 러 리 는 whatwg - fetch, node - fetch, isomorphic - fetch 가 있 습 니 다.whatwg - fetch 는 poly fill 을 만 들 었 습 니 다. fetch 를 지원 하지 않 는 browser 도 fetch 를 사용 할 수 있 습 니 다. node - fetch 는 node 에서 실 행 됩 니 다. isomorphic - fetch 는 앞의 두 가 지 를 패키지 로 했 습 니 다. browser 에서 도 달 릴 수 있 고 node 에서 도 달 릴 수 있 습 니 다.그리고 다음은 간단 한 fetch 차단기 의 실현 입 니 다.
//bread-fetch.js


var oldFetch = global.fetch

var newFetch = function (url, options={}) {
  let request = {
      url,
      options
  }

  return new Promise((resolve, reject) => {

    if (this.interceptors.length > 0) {
        //          
        this.runInterceptors(0, request)
        .then(req => {
            oldFetchFun(this,req)
            .then((res)=>{
                resolve(res);
            })
            .catch(err => {
                reject(err)
            });
        })
    } else {
        oldFetchFun(this, request)
        .then((res)=>{
            resolve(res);
        })
        .catch(err => {
            reject(err)
        });
    }

  });
}

var oldFetchFun = function (that, request) {
    return new Promise((resolve, reject) => {
        //      
        var timeout = request.options.timeout
        var timer
        if (timeout) {
            timer = setTimeout(function(){
                            reject(new Error("fetch timeout"))
                        }, timeout );
        }
        console.log('oldFetch request',request)
        oldFetch(request.url, request.options)
        .then(res=>{
            console.log('oldFetch res',res);
            return res.json();
        })
        .then(res => {
            console.log('oldFetch res json',res)
            //          
            let response = res
            if (that.interceptors_after.length > 0) {
                that.runInterceptorsAfter(0, response)
                .then(data => {
                    resolve(data);
                })
            }
        })
        .catch(err => {
            console.log('err',err)
            reject(err)
        });
    })
}

var breadFetch = function () {
}

breadFetch.prototype.newFetch = newFetch  

//fetch   
breadFetch.prototype.interceptors = []
breadFetch.prototype.interceptors_after = []
breadFetch.prototype.runInterceptors = function (i, request) {
  var _that = this
  if(i===0) this.interceptors_after = []

  return new Promise((resolve, reject) => {
    if (i >= this.interceptors.length) resolve(request)
    this.interceptors[i](request, function (callback) {
        if(callback){
            //callback           
            _that.interceptors_after.push(callback)
        }
        _that.runInterceptors(++i, request).then(req => {
            resolve(req)
        })   
    })
  })
}

breadFetch.prototype.runInterceptorsAfter = function (i, response) {
  var _that = this
  return new Promise((resolve, reject) => {
    if (i >= this.interceptors_after.length) resolve(response)
    this.interceptors_after[i](response, function () {
        _that.runInterceptorsAfter(++i, response).then(res => {
            resolve(res)
        })   
    })
  })
}

let objFetch = new breadFetch()
let fetch = function (url, options = {}) {
     return new Promise((resolve, reject) => {
         objFetch.newFetch(url, options)    
         .then(data => {
             resolve(data);
         })
         .catch(err => {
             reject(err)
         });
     })
}

export default objFetch
export { fetch } 



원 리 는 매우 간단 합 니 다. 원생 의 fetch 를 밀봉 하고 두 개의 배열 을 유지 하 며 요청 전의 작업 과 요청 후의 작업 을 각각 저장 하고 새로운 fetch api 로 요청 하 며 순서대로 이 작업 을 수행 하여 데 이 터 를 차단 합 니 다.
사용 예시:

//index.js

import storage, { MyStorage } from './storage/storage';
import breadFetch, { fetch } from './util/bread-fetch'

global.fetch = fetch

//fetch      token url  token
breadFetch.interceptors.push((req, next) => {
  console.log('interceptors1')
  if (req.url.includes('/api/login') || req.url.includes('/api/signup')) {
      next()
      return
  }
  MyStorage.load('login-token',(token)=>{
      console.log('login-token',token)
      if (req.url.includes('?')) {
        req.url = req.url + '&token=' + token
      } else {
        req.url = req.url + '?token=' + token
      }
      next()
    },() => {
      console.log('not found token, please login')
    },() => {
      console.log('token expire')
    })

})
breadFetch.interceptors.push((req, next) => {
  console.log('interceptors2')
  next()
})
breadFetch.interceptors.push((req, next) => {
  console.log('interceptors3')
  next((res, after) => {
    console.log('interceptorsAfter1')
    after()
  }) 
})

breadFetch.interceptors.push((req, next) => {
  console.log('interceptors4')
  next((res, after) => {
    console.log('interceptorsAfter2')
    // if (res.body.code === 302) {
    //   window.location = res.body.uri
    // }
    after()
  })
})
//signin.js

export function login (username, password) {
  return (dispatch, getState) => {
    return new Promise((resolve, reject) => {
        let params = { username, password }
        console.log('params',params)

        fetch(`${config.host}:${config.port}/api/login`, {
          method: 'post',
          headers: {
            //'Accept': 'application/json, text/plain, */\*',
            'Accept': 'application/json',
            'Content-Type': 'application/json'
            //'Content-Type': 'application/x-www-form-urlencoded'
          },
          body: JSON.stringify(params)
        })
        // .then(res=>res.json()) 
        .then((data) => {
              console.log('data',data)
              dispatch(signinResult(data.success)) 
              if (data.success) {
                MyStorage.save('login-token',{token: data.token})
                resolve()
              }
        })
        .catch((err) => {  
          console.warn(err);  
        })
        .done();
    })
  }
}


좋은 웹페이지 즐겨찾기