正經寫文章
平時開發裏,先請求一個 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