1

正经写文章

平时开发里,先请求一个 token ,然后后面的请求都要带上这个 token 来进行认证或者授权,是一个常见的需求

那要怎么搞呢?还是一个先后,控制异步流程的的问题,就是先拿到 token 再进行后面的请求就好了。相信 promise 大家已经用得很泛滥了:

let tokenPromise = new Promise(...) // 拿到 token
tokenPromise.then()... // 拿到 token 后去拿数据1
tokenPromise.then()... // 拿到 token 后去拿数据2
tokenPromise.then()... // 拿到 token 后去拿数据3
...

如果向上面这样组织那就完全没问题了。但是实际上一般也不会这样写吧,好蠢。。。但是计算机就是用来帮我们做这种蠢的重复性工作的,我们稍微变通一下,原理还是一样,只是代码写好看或者写少一点就好了

假设我们都是用 XMLHttpRequest 来发起请求的话(谁能告诉我为什么XML是大写Http却不是。。。),我们可以在 xhr.send() 上做点手脚,把这个函数再包多一层,在里面叫它帮我们调用 tokenPromise.then()。先做好准备工作:

首先我先用 easy-mock 模拟了两个接口,一个返回 token,一个返回 message

https://easy-mock.com/mock/5b8fea568eee36669a6b5523/example/token
{
  "data": {
    "token": "a_mock_token"
  }
}

https://easy-mock.com/mock/5b8fea568eee36669a6b5523/example/message
{
  "data": {
    "message": "你好"
  }
}

然后用 jQuery 的 ajax 发请求(只要是用了 XMLHttpRequest 对象,都ok):

<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>

接下来可以写代码了

// 先拿 token
var tokenPromise = new Promise((resovle, reject) => {
  // 清除缓存里的token
  localStorage.removeItem('token')
  $.ajax({
    type: 'GET',
    url: 'https://easy-mock.com/mock/5b8fea568eee36669a6b5523/example/token',
    success(res) {
      let token = res.data.token
      localStorage.setItem('token', token)
      resovle(token)
    },
    fail(err) {
      reject(err)
    }
  })
})

// 对 xhr.send 再包多一层
var originSend = XMLHttpRequest.prototype.send
XMLHttpRequest.prototype.send = function () {
  var args = arguments
  var self = this
  var fn = function () {
    var token = localStorage.getItem('token')
    // 假如把 token 放在请求头里
    self.setRequestHeader('token', token)
    console.log('后续请求token: ', token)
    originSend.apply(self, args)
  }
  // tokenPromise resolved 了才会执行后续的请求
  tokenPromise.then(fn)
}

// 后续其他请求, Network 看一下,请求已经带上 token 了
$.ajax({
  type: 'GET',
  url: 'https://easy-mock.com/mock/5b8fea568eee36669a6b5523/example/message',
  success(res) {
    console.log(res)
  },
  fail(err) {
    console.log(err)
  }
})

完整的代码

当然这只是一个大概的思路,你要用 axios 而不用 $.ajax ,或者是在小程序里对 wx.request() 包多一层而不是对 xhr.send() 包多一层都是类似的。希望我们能写出更多野鸡的写法

自言自语

最近在认真学习 promise,觉得 史上最易读懂的 Promise/A+ 完全实现 这篇文章真的挺棒的,起码能看懂一点了

然后有看到 fly (一个类似于axios的ajax库)直接就把我们上述这个先请求 token 的功能写在文档里了,并且这个作者还写了一个 Ajax-hook 来拦截 ajax 请求

所以就强行给博客拔拔草 :D


acfasj
124 声望11 粉丝

又不是不能用


« 上一篇
节流和防抖动