wendux / flyio-issues

flyio issues
0 stars 0 forks source link

flyio-拦截器 #23

Open wendux opened 6 years ago

wendux commented 6 years ago

https://wendux.github.io/dist/#/doc/flyio/interceptor

brandonhulala commented 6 years ago

先赞为敬,顺便想问一下,对于"在响应拦截器中执行异步任务",如果在使用"新的"fly实例请求获取token之前有一个异步操作(例如微信小程序中的wx.login方法),如何处理?

AllenForward commented 6 years ago

@brandonhulala 如果一个同时发送两个请求,两个请求都是token过去需要重新登录获取code,那不是要登录两次吗?

wendux commented 6 years ago

@AllenForward @brandonhulala fly.lock和fly.unlock了解一下

:octocat: From gitme Android

AllenForward commented 6 years ago

fly.lock()不能阻止执行登录啊.

wendux commented 6 years ago

可以的,一旦调用fly.lock(),那么后续请求都会进入一个队列。你有两个请求依赖登录,假设第一个请求先进入拦截器,然后发现没有token,然后调用fly.lock(),那么当前fly实例被锁定,你第二个请求则会进入队列等待。然后你用新的fly实例去请求token,请求完成后调用unlock(),第二个请求就会进入拦截器,这时token已经有了,你在将token设置到header,如示例中的request.headers["csrfToken"]=csrfToken,那么第二个请求就可以成功。请求token只需要一次。

AllenForward commented 6 years ago

嗯,谢谢,这个是在请求拦截器中设置的,我这里没有问题,我的问题是在响应拦截器中,页面加载时同时请求了两个接口,两个接口返回的状态码都表示token已过期,所以我在这里判断如果状态码表示token过期的话就重新登录获取新的token,但是这里登录会执行两次,因为有两个请求的返回。

wendux commented 6 years ago

@AllenForward 响应拦截器中的话 你可以在第一次请求失败后 然后登录 登录成功后记录一个时间戳,第二个请求进入响应拦截器的话,先看看时间差是否小于一个阀值(认为已经重新登录成功)…… 注意,在响应拦截器中应该调用响应拦截器的lock和unlock方法,fly.lock和fly.unlock是请求拦截器的锁定和解锁方法。

:octocat: From gitme Android

shiweiqi19930328 commented 6 years ago

使用场景:关键字模糊搜索,input事件不断被触发,如果前面的请求没响应,如何abort()掉?

AllenForward commented 6 years ago

有谁在小程序请求拦截器中遇到过wx.setStorageSync()方法不执行的问题吗.

apiaoqzh commented 6 years ago

我按照上面的例子照猫画虎,结果发现,finally并没有执行

qmRequest.interceptors.request.use(async function (request) {
  const auth = wx.getStorageSync('auth')
  if (auth) {
    // 当前Storage中包含了auth信息,直接拿来用,不要管有没有过期,如果过期后端会告诉我们401,到时候再response的拦截器里做retry就好了.
    request.headers['Authorization'] = auth
    return request
  } else {
    // 当前Storage中未包含auth信息,是新人,走login获取进行oAuth,获取token
    // 所有请求队列冻结,等待oAuth结果
    qmRequest.lock()
    let code = await oAuthMethods.wxLogin()
    console.log('code:', code)
    return oAuthRequest.post('login', {
      code
    })
      .then((res) => {
        // 获取oAuth的结果
        let newAuth = `${res.data.meta.token_type} ${res.data.meta.access_token}`
        wx.setStorageSync('auth', newAuth)
        wx.setStorageSync('session_key', res.data.session_key)
        request.headers['Authorization'] = newAuth
        console.log('oAuth end')
        return Promise.resolve(request)
      })
      .finally(() => {
        // 释放后续请求
        console.log('unlock')
        qmRequest.unlock()
      })
  }
})
apiaoqzh commented 6 years ago

原来是小程序api没有finally......

wendux commented 6 years ago

@apiaoqzh finally 是promise新Api ,小程序还不支持

:octocat: From gitme Android

AllenForward commented 6 years ago

你在请求拦截器里面使用wx.setStorageSync同步存储在真机上面没问题吗? @apiaoqzh

liuzz1024 commented 5 years ago

@wendux 在“响应拦截器”当中,通过function(error)捕捉到<401,请登录>,代码如下:

   function (error) {
    if(error.status === 401) {
      // console.log('先锁住请求')
      this.lock();
      return tokenService.login()
      .then((token) => {
        console.log('token已更新')
        error.request.headers.Authorization = token;  
      })
      .finally(() => {
        console.log('解锁队列');
        this.unlock();
      })      
      .then(() => {
        console.log('重新发起新的请求');
        // 重新发起新的请求
        return Rxports.ajax(error.request)
      })

    }
  }

即使我预先调用了this.lock(),页面如果存在多个请求,则会多次调用login(),导致重复请求token的情况。