後續請求都要帶上 token ?

正經寫文章

平時開發裏,先請求一個 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章