知識 分享 互助 懶人建站

    懶人建站專注于網頁素材下載,提供網站模板、網頁設計、ps素材、圖片素材等,服務于【個人站長】【網頁設計師】和【web開發從業者】的代碼素材與設計素材網站。

    懶人建站提供網頁素材下載、網站模板
    知識 分享 互助!

    fetch的用法(fetch新一代ajax請求方案)

    作者:佳明媽 來源:web前端開發 2016-10-17 人氣:
    fetch的用法,這篇fetch文章轉載自大神的博客,原文已對fetch的用法闡述很明白,沒必要在畫蛇添足,原文地址:http://www.html5online.com.cn/articles/2015051301.html 來自www.html5online.com.cn的一篇f

    fetch的用法,這篇fetch文章轉載自大神的博客,原文已對fetch的用法闡述很明白,沒必要在畫蛇添足,原文地址:http://www.html5online.com.cn/articles/2015051301.html

    來自www.html5online.com.cn的一篇fetch的用法

    基本的Fetch請求

    讓我們首先來比較一個XMLHttpRequest使用示例與fetch方法的使用示例。該示例向服務器端發出請求,得到響應并使用JSON將其解析。

    XMLHttpRequest

    一個XMLHttpRequest需要設置兩個事件回調函數,一個用于獲取數據成功時調用,另一個用于獲取數據失敗時調用,以及一個open()方法調用及一個send()方法調用。

    function reqListener(){
        var data=JSON.parse(this.responseText);
        console.log(data);
    }
    function reqError(err){
        console.log("Fetch錯誤:"+err);
    }
    var oReq=new XMLHttpRequest();
    oReq.onload=reqListener;
    oReq.onerror=reqError;
    oReq.open("get","/students.json",true);
    oReq.send();

    Fetch

    一個fetch()方法的使用代碼示例如下所示:

    fetch("/students.json")
    .then(
        function(response){
            if(response.status!==200){
                console.log("存在一個問題,狀態碼為:"+response.status);
                return;
            }
            //檢查響應文本
            response.json().then(function(data){
                console.log(data);
            });
        }
    )
    .catch(function(err){
        console.log("Fetch錯誤:"+err);
    });

    在上面這個示例中,我們在使用JSON解析響應前首先檢查響應狀態碼是否為200。

    一個fetch()請求的響應為一個Stream對象,這表示當我們調用json()方法,將返回一個Promise對象,因為流的讀取將為一個異步過程。

    響應元數據

    在上一個示例中我們檢查了Response對象的狀態碼,同時展示了如何使用JSON解析響應數據。我們可能想要訪問響應頭等元數據,代碼如下所示:

    fetch("/students.json")
    .then(
        function(response){
            console.log(response.headers.get('Content-Type'));
            console.log(response.headers.get('Date'));
            console.log(response.status);
            console.log(response.statusText);
            console.log(response.type);
            console.log(response.url);
        }
    )

    響應類型

    當我們發出一個fetch請求時,響應類型將會為以下幾種之一:“basic”、“cors”或“opaque”。這些類型標識資源來源,提示你應該怎樣對待響應流。

    當請求的資源在相同域中時,響應類型為“basic”,不嚴格限定你如何處理這些資源。

    如果請求的資源在其他域中,將返回一個CORS響應頭。響應類型為“cors”。“cors”響應限定了你只能在響應頭中看見“Cache-Control”、“Content-Language”、“Content-Type”、“Expires”、“Last-Modified”以及“Progma”。

    一個“opaque”響應針對的是訪問的資源位于不同域中,但沒有返回CORS響應頭的場合。如果響應類型為“opaque”,我們將不能查看數據,也不能查看響應狀態,也就是說我們不能檢查請求成功與否。目前為止不能在頁面腳本中請求其他域中的資源。

    你可以為fetch請求定義一個模式以確保請求有效。可以定義的模式如下所示:

    • "same-origin":只在請求同域中資源時成功,其他請求將被拒絕。
    • "cors":允許請求同域及返回CORS響應頭的域中的資源。
    • "cors-with-forced-preflight":在發出實際請求前執行preflight檢查。
    • "no-cors"針對的是向其他不返回CORS響應頭的域中的資源發出的請求(響應類型為“opaque”),但如前所述,目前在頁面腳本代碼中不起作用。

    為了定義模式,在fetch方法的第二個參數中添加選項對象并在該對象中定義模式:

    fetch("http://www.html5online.com.cn/cors-enabled/students.json",{mode:"cors"})
    .then(
        function(response){
            console.log(response.headers.get('Content-Type'));
            console.log(response.headers.get('Date'));
            console.log(response.status);
            console.log(response.statusText);
            console.log(response.type);
            console.log(response.url);
        }
    )
    .catch(function(err){
        console.log("Fetch錯誤:"+err);
    });

    Promise方法鏈

    Promise API的一個重大特性是可以鏈接方法。對于fetch來說,這允許你共享fetch請求邏輯。

    如果使用JSON API,你需要檢查狀態并且使用JSON對每個響應進行解析。你可以通過在不同的返回Promise對象的函數中定義狀態及使用JSON進行解析來簡化代碼,你將只需要關注于處理數據及錯誤:

    function status(response){
        if(response.status>=200 && response.status<300){
            return Promise.resolve(response);
        }
        else{
            return Promise.reject(new Error(response.statusText));
        }
    }
    function json(response){
        return response.json();
    }
    fetch("/students.json")
    .then(status)
    .then(json)
    .then(function(data){
        console.log("請求成功,JSON解析后的響應數據為:",data);
    })
    .catch(function(err){
        console.log("Fetch錯誤:"+err);
    });

    在上述代碼中,我們定義了status函數,該函數檢查響應的狀態碼并返回Promise.resolve()方法或Promise.reject()方法的返回結果(分別為具有肯定結果的Promise及具有否定結果的Promise)。這是fetch()方法鏈中的第一個方法。如果返回肯定結果,我們調用json()函數,該函數返回來自于response.json()方法的Promise對象。在此之后我們得到了一個被解析過的JSON對象,如果解析失敗Promise將返回否定結果,導致catch段代碼被執行。

    這樣書寫的好處在于你可以共享fetch請求的邏輯,代碼容易閱讀、維護及測試。

    POST請求

    在Web應用程序中經常需要使用POST方法提交頁面中的一些數據。

    為了執行POST提交,我們可以將method屬性值設置為post,并且在body屬性值中設置需要提交的數據。

    fetch(url,{
        method:"post",
        headers:{
            "Content-type":"application:/x-www-form-urlencoded:charset=UTF-8"
        },
        body:"name=lulingniu&age=40"
    })
    .then(status)
    .then(json)
    .then(function(data){
        console.log("請求成功,JSON解析后的響應數據為:",data);
    })
    .catch(function(err){
        console.log("Fetch錯誤:"+err);
    });

    使用Fetch請求發送憑證

    你可能想要使用Fetch發送帶有諸如cookie之類的憑證的請求。你可以在選項對象中將credentials屬性值設置為“include”:

    fetch(url,{
    credentials:"include"
    })

    來自segmentfault.com的一篇fetch用法介紹文章

    雖然有裝逼的感覺,不過文章寫的還是不錯,還是應該感謝作者,原文地址:http://www.html5online.com.cn/articles/2015051301.html

    Fetch API 是基于 Promise 設計,有必要先學習一下 Promise,推薦閱讀 MDN Promise 教程。舊瀏覽器不支持 Promise,需要使用 polyfill es6-promise 。

    本文不是 Fetch API 科普貼,其實是講異步處理和 Promise 的。Fetch API 很簡單,看文檔很快就學會了。推薦 MDN Fetch 教程 和 萬能的WHATWG Fetch 規范

    Why Fetch

    XMLHttpRequest 是一個設計粗糙的 API,不符合關注分離(Separation of Concerns)的原則,配置和調用方式非常混亂,而且基于事件的異步模型寫起來也沒有現代的 Promise,generator/yield,async/await 友好。

    Fetch 的出現就是為了解決 XHR 的問題,拿例子說明:

    使用 XHR 發送一個 json 請求一般是這樣:

    var xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    xhr.responseType = 'json';
    
    xhr.onload = function() {
      console.log(xhr.response);
    };
    
    xhr.onerror = function() {
      console.log("Oops, error");
    };
    
    xhr.send();

    使用 Fetch 后,頓時看起來好一點

    fetch(url).then(function(response) {
      return response.json();
    }).then(function(data) {
      console.log(data);
    }).catch(function(e) {
      console.log("Oops, error");
    });

    使用 ES6 的 箭頭函數 后:

    fetch(url).then(response => response.json())
      .then(data => console.log(data))
      .catch(e => console.log("Oops, error", e))

    現在看起來好很多了,但這種 Promise 的寫法還是有 Callback 的影子,而且 promise 使用 catch 方法來進行錯誤處理的方式有點奇怪。不用急,下面使用 async/await 來做最終優化:

    注:async/await 是非常新的 API,屬于 ES7,目前尚在 Stage 1(提議) 階段,這是它的完整規范。使用 Babel 開啟 runtime 模式后可以把 async/await 無痛編譯成 ES5 代碼。也可以直接使用 regenerator 來編譯到 ES5。

    try {
      let response = await fetch(url);
      let data = response.json();
      console.log(data);
    } catch(e) {
      console.log("Oops, error", e);
    }
    // 注:這段代碼如果想運行,外面需要包一個 async function

    duang~~ 的一聲,使用 await 后,寫異步代碼就像寫同步代碼一樣爽。await 后面可以跟 Promise 對象,表示等待 Promiseresolve() 才會繼續向下執行,如果 Promise 被 reject() 或拋出異常則會被外面的 try...catch 捕獲。

    Promise,generator/yield,await/async 都是現在和未來 JS 解決異步的標準做法,可以完美搭配使用。這也是使用標準 Promise 一大好處。最近也把項目中使用第三方 Promise 庫的代碼全部轉成標準 Promise,為以后全面使用 async/await 做準備。

    另外,Fetch 也很適合做現在流行的同構應用,有人基于 Fetch 的語法,在 Node 端基于 http 庫實現了 node-fetch,又有人封裝了用于同構應用的 isomorphic-fetch

    注:同構(isomorphic/universal)就是使前后端運行同一套代碼的意思,后端一般是指 NodeJS 環境。

    總結一下,Fetch 優點主要有:

    1. 語法簡潔,更加語義化

    2. 基于標準 Promise 實現,支持 async/await

    3. 同構方便,使用 isomorphic-fetch

    Fetch 啟用方法

    下面是重點↓↓↓

    先看一下 Fetch 原生支持率:
    fetch的用法

    原生支持率并不高,幸運的是,引入下面這些 polyfill 后可以完美支持 IE8+ :

    1. 由于 IE8 是 ES3,需要引入 ES5 的 polyfill: es5-shim, es5-sham

    2. 引入 Promise 的 polyfill: es6-promise

    3. 引入 fetch 探測庫:fetch-detector

    4. 引入 fetch 的 polyfill: fetch-ie8

    5. 可選:如果你還使用了 jsonp,引入 fetch-jsonp

    6. 可選:開啟 Babel 的 runtime 模式,現在就使用 async/await

    Fetch polyfill 的基本原理是探測是否存在 window.fetch 方法,如果沒有則用 XHR 實現。這也是 github/fetch 的做法,但是有些瀏覽器(Chrome 45)原生支持 Fetch,但響應中有中文時會亂碼,老外又不太關心這種問題,所以我自己才封裝了 fetch-detector 和fetch-ie8 只在瀏覽器穩定支持 Fetch 情況下才使用原生 Fetch。這些庫現在每天有幾千萬個請求都在使用,絕對靠譜!

    終于,引用了這一堆 polyfill 后,可以愉快地使用 Fetch 了。但要小心,下面有坑:

    Fetch 常見坑

    • Fetch 請求默認是不帶 cookie 的,需要設置 fetch(url, {credentials: 'include'})

    • 服務器返回 400,500 錯誤碼時并不會 reject,只有網絡錯誤這些導致請求不能完成時,fetch 才會被 reject。

    竟然沒有提到 IE,這實在太不科學了,現在來詳細說下 IE

    IE 使用策略

    所有版本的 IE 均不支持原生 Fetch,fetch-ie8 會自動使用 XHR 做 polyfill。但在跨域時有個問題需要處理。

    IE8, 9 的 XHR 不支持 CORS 跨域,雖然提供 XDomainRequest,但這個東西就是玩具,不支持傳 Cookie!如果接口需要權限驗證,還是乖乖地使用 jsonp 吧,推薦使用 fetch-jsonp。如果有問題直接提 issue,我會第一時間解決。

    標準 Promise 的不足

    由于 Fetch 是典型的異步場景,所以大部分遇到的問題不是 Fetch 的,其實是 Promise 的。ES6 的 Promise 是基于 Promises/A+ 標準,為了保持簡單簡潔,只提供極簡的幾個 API。如果你用過一些牛 X 的異步庫,如 jQuery(不要笑) 、Q.js 或者 RSVP.js,可能會感覺 Promise 功能太少了。

    沒有 Deferred

    Deferred 可以在創建 Promise 時可以減少一層嵌套,還有就是跨方法使用時很方便。
    ECMAScript 11 年就有過 Deferred 提案,但后來沒被接受。其實用 Promise 不到十行代碼就能實現 Deferred:es6-deferred。現在有了 async/await,generator/yield 后,deferred 就沒有使用價值了。

    沒有獲取狀態方法:isRejected,isResolved

    標準 Promise 沒有提供獲取當前狀態 rejected 或者 resolved 的方法。只允許外部傳入成功或失敗后的回調。我認為這其實是優點,這是一種聲明式的接口,更簡單。

    缺少其它一些方法:always,progress,finally

    always 可以通過在 then 和 catch 里重復調用方法實現。finally 也類似。progress 這種進度通知的功能還沒有用過,暫不知道如何替代。

    Fetch 替換 XHR 只是時間問題,現在看到國外很多新的庫都默認使用了 Fetch。

    最后再做一個大膽預測:由于 async/await 這類新異步語法的出現,第三方的 Promise 類庫會逐漸被標準 Promise 替代,使用 polyfill 是現在比較明智的做法。
    原文地址:http://www.html5online.com.cn/articles/2015051301.html
    原文地址:http://www.html5online.com.cn/articles/2015051301.html

    ↓ 查看全文

    fetch的用法(fetch新一代ajax請求方案)由懶人建站收集整理,您可以自由傳播,請主動帶上本文鏈接

    懶人建站就是免費分享,覺得有用就多來支持一下,沒有能幫到您,懶人也只能表示遺憾,希望有一天能幫到您。

    fetch的用法(fetch新一代ajax請求方案)-最新評論

    老子是皇帝在线客服