如何使用 fetch ,加請求頭, ajax 和 fetch 和 axios 的區(qū)別

----歡迎查看我的博客----

什么是fetch

??我們之前,過度過來都在用ajax,那么什么是 Fetch ,F(xiàn)etch 是新的游覽器對象, 等同于 XMLHttpRequest對象 。它提供了許多與 XMLHttpRequest 相同的功能,但被設(shè)計成更具可擴展性和高效性。

image

ajax

??廢話不多說我們來看一下傳統(tǒng)的ajax。

var xhr;
if (window.XMLHttpRequest) {
   xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
   try {
     xhr = new ActiveXObject('Msxml2.XMLHTTP');
   } catch (e) {
     try {
       xhr = new ActiveXObject('Microsoft.XMLHTTP');
     } catch (e) {}
   }
}
if (xhr) {
   xhr.onreadystatechange = () =>{
       if (xhr.readyState === 4) {
          if (xhr.status === 200) {
             console.log(xhr.responseText); //返回值傳callback
          } else {
                //failcallback
             console.log('There was a problem with the request.');
          }
       } else {
          console.log('still not ready...');
       }
    };
   xhr.open('POST', 'https://www.baidu.com', true);
   // 設(shè)置 Content-Type 為 application/x-www-form-urlencoded
   // 以表單的形式傳遞數(shù)據(jù)
   xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
   xhr.send('username=admin&password=root');
}

??好我們來做層封裝,讓他變成我們 jQuery 的 ajax post
如這種形式:

$.ajax({
    method: 'POST', //請求方式
    url: '/api', //url
    data: { username: 'admin', password: 'root' }, //值
    success:function(data){ //成功回掉
        console.log(data)
    },
    error:function(err){
        console.log(err)
    }
})

好的封裝開始:

const $ = {};
$.ajax = (obj)=>{
    var xhr;
    if (window.XMLHttpRequest) {
       xhr = new XMLHttpRequest();
    } else if (window.ActiveXObject) { // IE
       try {
         xhr = new ActiveXObject('Msxml2.XMLHTTP');
       } catch (e) {
         try {
           xhr = new ActiveXObject('Microsoft.XMLHTTP');
         } catch (e) {}
       }
    }
    if (xhr) {
       xhr.onreadystatechange = () =>{
           if (xhr.readyState === 4) {
              if (xhr.status === 200) {
                 obj.success(xhr.responseText); //返回值傳callback
              } else {
                    //failcallback
                 obj.error('There was a problem with the request.');
              }
           } else {
              console.log('still not ready...');
           }
        };
       xhr.open(obj.method, obj.url, true);
       // 設(shè)置 Content-Type 為 application/x-www-form-urlencoded
       // 以表單的形式傳遞數(shù)據(jù)
       xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
       xhr.send(util(obj.data));//處理body數(shù)據(jù)
    }
    
    //處理數(shù)據(jù)
    const util = (obj)=>{
        var str = ''
        for (key in obj){
            str += key +'='+obj[key]+'&'

        }
        return str.substring(0,str.length-1)
    }
    
}

??ok,咱們已經(jīng)封裝完畢,可以使用了,可是你會發(fā)現(xiàn),這種書寫方式很混亂,body,hearder亂七八糟,還有回掉地獄的問題。好的fetch出來了。

fetch的出現(xiàn)

??我們說了,一種東西的誕生有它的道理,他首先解決了回掉地獄的問題因為返回一個 promise 對象 ,對 promise 對象不是很熟悉的同學(xué)可以看這篇文章: 你就需要這篇文章,帶你搞懂實戰(zhàn)的 Promise 對象。同樣既然是 promise 對象我們就可以使用 es7 的 async / await 戳這里。好了廢話不多說我們看看最基礎(chǔ)的 fetch 怎么寫吧 。

fetch(url, options).then(function(response) {
  // handle HTTP response
}, function(error) {
  // handle network error
})

??就是這么方便,就是這么簡單。 fetch 會先發(fā)起一個 option 的請求,確定是否連接成功,然后再發(fā)送正式的請求 ,就好比 xhr.readyState === 4 這個一個道理。那有同學(xué)就問了,我的邏輯比較復(fù)雜 。我的 fetch 要加請求頭,參數(shù)我要傳參傳 formData 不是 json。
我們來看fetch發(fā)送formdata:

fetch(url,{
    method:"post",
    headers:{
        "Content-type":"application:/x-www-form-urlencoded:charset=UTF-8"
    },
    body:"name=admin&password=123456"
}).then(function(response){
    if(response.ok){
        response.json().then(json => {
              console.log(json.result)
        })
    }
}).catch(function(err){
    console.log("Fetch錯誤:"+err);
});

??發(fā)送json格式也非常簡單。

fetch(url,{
    method:"post",
    headers:{
       'Content-Type':'application/json; charset=UTF-8'
    },
    body:JSON.stringify({name:'admin',password:123456})
}).then(function(response){
    if(response.ok){
        response.json().then(json => {
              console.log(json.result)
        })
    }
}).catch(function(err){
    console.log("Fetch錯誤:"+err);
});

中止 取消 fetch

瀏覽器已經(jīng)開始為 AbortControllerAbortSignal 接口(也就是Abort API)添加實驗性支持,允許像 Fetch 和 XHR 這樣的操作在還未完成時被中止 。請參閱接口頁面了解更多詳情。但是目前對游覽器的支持并不很好,所以我們其實可以換一種思路, 取消 fetch 我們可以從另外一個面入手 ---- 可以取消 promise 。原生的當(dāng)然不行了,所以我們這里用到了 bluebird

例如多個 fetch:


//傳統(tǒng) promise
var promises = [];
for (var i = 0; i < fileNames.length; ++i) {
    promises.push(fs.readFileAsync(fileNames[i]));
}
Promise.all(promises).then(function() {
    console.log("done");
});

// Using Promise.map:
import Promise from 'bluebird'
Promise.map(fileNames, function(fileName) {
    // Promise.map awaits for returned promises as well.
    return fs.readFileAsync(fileName);
}).then(function() {
    console.log("done");
});

終止取消多個 fetch:

import Promise from 'bluebird'
Promise.map(fileNames, function(fileName) {
    // Promise.map awaits for returned promises as well.
    return fs.readFileAsync(fileName).then(()=>{
                //如果flag = true 就中斷。
                if (flag){
                  throw new Error('中斷')
                }
            });;
}).then(function() {
    console.log("done");
}).catch(function (err) {
    console.log('Error', err.message)
});

如果取消單個 promise 可以用 .cancel 方法,具體看 bluebird 文檔。

Axios 的出現(xiàn)

??從文檔中我們可以看出為什么這個會火 ,axios 他的功能非常強大,包括 取消請求 ,進度處理等等。但是我們看的是本質(zhì)還是 ajax ,在基礎(chǔ)上進行了封裝和功能的添加

XMLHttpRequests
支持 Promise

//一個post請求

axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

結(jié)語

??其實我們看出來, ajax 和 Axios 在客戶端都是調(diào)用 XMLHttpRequests 對象 ,而我們的 fetch 是一個新的游覽器對象 。只不過 ajax 和 Axios 區(qū)別就是在 封裝了簡便的方法,并且提供了一個 promise 對象。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容