JS: 用 Promise 寫(xiě)一個(gè) axios

只要用過(guò) Vue蒋院,沒(méi)人會(huì)不知道 axios 這個(gè)庫(kù),他基乎取代了 jQuery 發(fā) ajax 的功能了参淹。今天我就用 Promise 來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 axios。

純 JS 發(fā) ajax

使用純 JS 發(fā) ajax 要 4 步偿曙。

  1. 創(chuàng)建 XMLHttpRequest 對(duì)象
  2. 使用 open 函數(shù)
  3. 設(shè)置 onreadystatechange 回調(diào)
  4. 使用 send 傳入請(qǐng)求數(shù)據(jù)
const xhr = new XMLHttpRequest()
xhr.open(method, url)
xhr.onreadystatechange =  () => {
    if (xhr.readyState === 4 && xhr.status === 200) {
        resolve(xhr.response)
    } else {
        reject(xhr.statusText)
    }
}
xhr.send(data)

上面的寫(xiě)法的對(duì)的,但是在 Promise 里是有坑的羔巢,下面會(huì)說(shuō)到望忆。

引入 Promise

Promise 傳入?yún)?shù)為一個(gè)函數(shù),而這個(gè)函數(shù)里面兩個(gè)參數(shù)分別是 resolve 函數(shù)和 reject 函數(shù)朵纷。

  1. 當(dāng) Promise 狀態(tài)變成 fulfilled 時(shí)(成功)炭臭,就調(diào)用 resolve
  2. 當(dāng) Promise 狀態(tài)變成 rejected 時(shí)(失敗)袍辞,就調(diào)用 reject

所以我們可能會(huì)寫(xiě)下在的代碼:

new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest()
    xhr.open(method, url)
    xhr.onreadystatechange = () => {
       if (xhr.readyState === 4 && xhr.status === 200) {
            resolve(xhr.response)
        } else {
            reject(xhr.statusText)
        }
    }
    xhr.send(data)
})

注意鞋仍,這里創(chuàng)建 Promise 對(duì)象的時(shí)候就會(huì)立刻,馬上去執(zhí)行 Promise 傳入那個(gè)函數(shù)里的代碼搅吁。但是 resolve 和 reject 還不會(huì)調(diào)用威创,現(xiàn)在 Promise 會(huì)進(jìn)入 pending (等待)狀態(tài)。

如果請(qǐng)求成功再去調(diào)用 resolve(此時(shí) pending 變成 fulfilled)谎懦,如果失敗會(huì)去調(diào)用 reject(此時(shí) pending 變成 rejected)肚豺。

就像我前面說(shuō)的,這里有一個(gè)坑〗缋梗現(xiàn)在的想法是希望 readyState 為 4(已經(jīng)響應(yīng)了)且 stats 為 200 (響應(yīng)成功了)就去調(diào)用 resolve 函數(shù)吸申。

首先我們要知道 Promise 的一個(gè)規(guī)則是:只要 Promise 狀態(tài)一改變就不會(huì)再去改變了。但是 onreadystatechange 是會(huì)一直被調(diào)用的。

一直在判斷 readyState 的值

他會(huì)一直查看 readyState 的值截碴,直到 readyState === 4 為止才不會(huì)再去調(diào)用 onreadystatechange 的回調(diào)梳侨。如果現(xiàn)在 readyState === 2 時(shí),按現(xiàn)在的代碼會(huì)去調(diào)用 reject(xhr.statusText)日丹,Promise 的狀態(tài)就會(huì)立馬變成 rejected走哺,狀態(tài)一旦確定就不會(huì)再改變了,也就是說(shuō)整個(gè)代碼下來(lái)只調(diào)用了 reject哲虾。

調(diào)用了 reject 就不會(huì)再去調(diào)用 resolve

正確的寫(xiě)法應(yīng)該是 readyState < 4 都不去調(diào)用丙躏,只有 4 時(shí)再去調(diào)用。

new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest()
    xhr.open(method, url)
    xhr.onreadystatechange =  () => {
        if (xhr.readyState !== 4) {
            return
        }
        if (xhr.status === 200) {
            resolve(xhr.response)
        } else {
            reject(xhr.statusText)
        }
    }
    xhr.send(data)
})

包裝

解決這個(gè)坑后我們應(yīng)該把上面的代碼包裝到一個(gè)函數(shù)里束凑。

function axios(ajaxObj) {
    const {url, method, data} = ajaxObj

    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest()
        xhr.open(method, url)
        xhr.onreadystatechange =  () => {
            if (xhr.readyState !== 4) {
                return
            }
            if (xhr.status === 200) {
                resolve(xhr.response)
            } else {
                reject(xhr.statusText)
            }
        }
        xhr.send(data)
    })
}

使用的時(shí)候就可以用 .then() 來(lái)使用了晒旅。

function sendRequest() {
    const ajaxObj = {
        url: 'https://cnodejs.org/api/v1/topics',
        method: 'GET',
        data: ''
    }
    axios(ajaxObj)
        .then((response) => {
            console.log('resolve')
            console.log(response)
        })
        .catch((error) => {
            console.error(error)
        })
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市湘今,隨后出現(xiàn)的幾起案子敢朱,更是在濱河造成了極大的恐慌,老刑警劉巖摩瞎,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異孝常,居然都是意外死亡旗们,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)构灸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)上渴,“玉大人,你說(shuō)我怎么就攤上這事喜颁〕淼” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵半开,是天一觀的道長(zhǎng)隔披。 經(jīng)常有香客問(wèn)我,道長(zhǎng)寂拆,這世上最難降的妖魔是什么奢米? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮纠永,結(jié)果婚禮上鬓长,老公的妹妹穿的比我還像新娘。我一直安慰自己尝江,他們只是感情好涉波,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般啤覆。 火紅的嫁衣襯著肌膚如雪苍日。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,829評(píng)論 1 290
  • 那天城侧,我揣著相機(jī)與錄音易遣,去河邊找鬼。 笑死嫌佑,一個(gè)胖子當(dāng)著我的面吹牛豆茫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播屋摇,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼揩魂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了炮温?” 一聲冷哼從身側(cè)響起火脉,我...
    開(kāi)封第一講書(shū)人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎柒啤,沒(méi)想到半個(gè)月后倦挂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡担巩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年方援,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涛癌。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡犯戏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拳话,到底是詐尸還是另有隱情先匪,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布弃衍,位于F島的核電站呀非,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏笨鸡。R本人自食惡果不足惜姜钳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望形耗。 院中可真熱鬧哥桥,春花似錦、人聲如沸激涤。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至送滞,卻和暖如春侠草,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背犁嗅。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工边涕, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人褂微。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓功蜓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親宠蚂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子式撼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • Promise 對(duì)象 Promise 的含義 Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函...
    neromous閱讀 8,702評(píng)論 1 56
  • 一著隆、Promise的含義 Promise在JavaScript語(yǔ)言中早有實(shí)現(xiàn)美浦,ES6將其寫(xiě)進(jìn)了語(yǔ)言標(biāo)準(zhǔn),統(tǒng)一了用法...
    Alex灌湯貓閱讀 820評(píng)論 0 2
  • //本文內(nèi)容起初摘抄于 阮一峰 作者的譯文案腺,用于記錄和學(xué)習(xí)访递,建議觀者移步于原文 概念: 所謂的Promise拷姿,...
    曾經(jīng)過(guò)往閱讀 1,231評(píng)論 0 7
  • Promise學(xué)習(xí)(上): 資料: JavaScript Promise迷你書(shū) 原著:azu / 翻譯:liubi...
    你隔壁的陌生人閱讀 563評(píng)論 0 1
  • 目錄:Promise 的含義基本用法Promise.prototype.then()Promise.prototy...
    BluesCurry閱讀 1,490評(píng)論 0 8