React Native Fetch封裝那點事...

每一門語言都離不開網絡請求,有本身的一套Networking Api。React Native使用的是Fetch。 今天咱們來談談與Fetch相關的一些事情。java

purpose

經過這篇文章,你將瞭解到如下幾點關於Fetch的獨家報道react

  • Fetch的簡單運用
  • Fetch的主要Api
  • Fetch使用注意事項
  • Fetch的Promise封裝

fetch

fetch的使用很是簡單,只需傳入請求的urlgit

fetch('https://facebook.github.io/react-native/movies.json');

固然是否請求成功與數據的處理,咱們還需處理成功與失敗的回調github

function getMoviesFromApiAsync() {
  return fetch('https://facebook.github.io/react-native/movies.json')
    .then((response) => response.json())
    .then((responseJson) => {
      return responseJson.movies;
    })
    .catch((error) => {
      console.error(error);
    });
}

經過response.json()將請求的返回數據轉化成json數據以便使用。經過.then來對數據進行轉化處理或最終暴露給調用者;.catch對異常的處理。web

以上就是一個簡單的網絡請求,該請求默認是get方式。那麼post又該如何請求呢?算法

Api & Note

在fetch中咱們直接傳入url進行請求,其實內部本質是使用了Request對象,只是將url出入到了Request對象中。json

const myRequest = new Request('https://facebook.github.io/react-native/movies.json');
 
const myURL = myRequest.url; // https://facebook.github.io/react-native/movies.jsonflowers.jpg
const myMethod = myRequest.method; // GET
 
fetch(myRequest)
  .then(response => response.json())
  .then(responseJson => {
    //todo
  });

若是咱們須要請求post,須要改變Request的method屬性。segmentfault

fetch('https://mywebsite.com/endpoint/', {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    firstParam: 'yourValue',
    secondParam: 'yourOtherValue',
  }),
});

很是簡單,在url後直接傳入{}對象,其中指定method使用post。react-native

相信你們應該都知道get與post的一個主要區別是get能夠在url上直接添加參數,而post爲了安全都不採用直接將參數追加到url上,而是使用body來傳給service端。緩存

在使用body前,這裏還需知道headers。下面某個post請求的headers信息

clipboard.png

須要注意的是Content-Type字段,它表明的是service端接收的數據類型,圖片中使用的是application/x-www-form-urlencoded。這對於咱們的body來講是很是重要的。只有匹配Content-Type的類型才能正確的傳遞參數信息。

示例的代碼使用的是application/json,因此body使用Json.stringify()進行參數轉換,而對於Content-Type爲application/x-www-form-urlencoded,須要使用queryString.stringify()。

Request中除了method、headers與body,還有如下屬性

  • Request.cache: 請求的緩存模式(default/reload/no-cache)
  • Request.context: 請求的上下文(audio/image/iframe)
  • Request.credentials: 請求的證書(omit/same-origin/include)
  • Request.destination: 請求的內容描述類型
  • Request.integrity: 請求的 subresource integrity
  • Request.mode: 請求的模式(cors/no-cors/same-origin/navigate)
  • Request.redirect: 請求的重定向方式(follow/error/manual)
  • Request.referrer: 請求的來源(client)
  • Request.referrerPolicy: 請求的來源政策(no-referrer)
  • Request.bodyUsed: 聲明body是否使用在response中

請求成功以後,使用.then來轉換數據,使用最多的是Body.json(),固然你也可使用如下的幾種數據轉換類型

  • Body.arrayBuffer
  • Body.blob
  • Body.formData
  • Body.text

以上是fetch請求相關的屬性與方法。若是你已經有所瞭解,那麼恭喜你對fetch的基本使用已通過關了,下面對fetch的使用進行封裝。

封裝

在實際開發中,url的host都是相同的,不一樣的是請求的方法名與參數。而對於不一樣的環境(debug|release)請求的方式也可能不一樣。例如:在debug環境中爲了方便調試查看請求的參數是否正確,咱們會使用get來進行請求。因此在封裝以前要明確什麼是不變的,什麼是變化的,成功與失敗的響應處理。

通過上面的分析,羅列一下封裝須要作的事情。

  • 不變的: host,headers,body.json()
  • 變化的: url,method,body
  • 響應方式: Promise(resolve/reject)
function convertUrl(url, params) {
    let realUrl = ApiModule.isDebug?
        url + "?" + queryString.stringify(Object.assign({}, params, commonParams)) : url;

    if (ApiModule.isDebug) {
        console.log("request: " + realUrl);
    }
    return realUrl;
}

首先對url與參數params進行拼接,若是爲debug模式將params拼接到url後。這裏使用到了Object.assign()將params與commonParams組合成一個{}對象。最終經過queryString.stringify轉化成string。

ApiModule.isDebug是原生傳遞過來的值,對於Android/IOS只需傳遞本身的ApiModule便可。
function getMethod() {
    return ApiModule.isDebug? "get": "post";
}

上述提到的get與post的請求時機。

const headers = {
    Accept: 'application/json',
    "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
};

在headers中Content-Type類型爲application/x-www-form-urlencode

function convertBody(params) {
    return ApiModule.isDebug? undefined : queryString.stringify(Object.assign({}, params, commonParams));
}

因爲debug模式使用的是get方式,但get規定是不能有body的,因此這裏使用了undefined來標識。同時爲了匹配headers中的Content-Type,params的轉化必須使用queryString.stringify;若是接受的是json,可使用JSON.stringify。

定義完以後fetch對外只需接受params參數便可。

async function fetchRequest(params){
    let body = convertBody(params);
    fetch(convertUrl(baseUrl, params),{
        method: method,
        headers: headers,
        body: body
    })
    .then((response) => response.json())
    .then((responseJson) => {
        //todo success
    })
    .catch((error) => {
        if (ApiModule.isDebug) {
            console.error("request error: " + error);
        };
        //todo error
    });
}

fetch的請求封裝完成,但咱們的成功與失敗的狀態並無通知給調用者,因此還須要一個回調機制。Promise是一個異步操做最終完成或者失敗的對象。它能夠接受兩個函數resolve、reject

const p = new Promise((resolve, reject){
    ...
    //success
    resolve('success')
    //error
    reject('error')
});
//use
p.then(success => {
        console.log(success);
    }, error => {
          console.log(error)    
});

將fetch請求放入到Promise的異步操做中,這樣一旦數據成功返回就調用resolve函數回調給調用者;失敗調用reject函數,返回失敗信息。而調用者只需使用Promise的.then方法等候數據的回調通知。下面來看下完整的fetch封裝。

async function fetchRequest(params){
    let body = convertBody(params);
    return new Promise(function(resolve, reject){
        fetch(convertUrl(baseUrl, params),{
            method: method,
            headers: headers,
            body: body
        })
        .then((response) => response.json())
        .then((responseJson) => {
            resolve(responseJson);
        })
        .catch((error) => {
            if (ApiModule.isDebug) {
                console.error("request error: " + error);
            };
            reject(error);
        });
    });
}

以後對fetch的使用就很是簡單了,只需傳入須要的參數便可。

fetchRequest({method: "goods.getInfo", goodsId: 27021599158370074})
.then(res =>{
    this.setState({
        shareInfo: res.data.shareInfo
    });
});

以上是有關fetch的所有內容,固然在React Native中還有其它的第三方請求庫:XMLHttpRequest,同時也支持WebSockets。感興趣的也能夠去了解一下,相信會有不錯的收穫。

精選文章

5分鐘吃透React Native Flexbox

ViewDragHelper之手勢操做神器

tensorflow-梯度降低,有這一篇就足夠了

七大排序算法總結(java)

拉粉環節:感受不錯的能夠來一波關注,掃描下方二維碼,關注公衆號,及時獲取最新知識技巧。

clipboard.png

相關文章
相關標籤/搜索