從零學React Native之14 網絡請求

通過HTTP或者HTTPS協議與網絡側服務器交換數據是移動應用中常見的通信方式。 node-fetch是RN推薦的請求方式。
React Native框架在初始化項目時, 引入了node-fetch包 (因爲npm3把依賴全部攤平了,node-fetch就在node_modules目錄下)

下面就是項目中引入的node-fetch的源碼:

聯網

聯網分爲發送請求和接受響應兩步。分開來分析下。

發送請求

發送http/https gong細分一下共有6個步驟
1. 確定並準備請求地址與協議
2. 確定請求中的HTTP方法
3. 準備請求中藥傳輸的消息頭
4. 準備身份驗證信息
5. 確定是否需要攜帶消息體/參數
6. 發出消息

我們以查詢號碼歸屬地這個地址演示下。

1. 確定並準備請求地址與協議

請求地址以http/https 開頭,爲了便於修改地址,通常將地址放在一個變量中。IOS9以上默認無法訪問http請求, 具體參考後面的注意事項。

let url=`http://apis.baidu.com/showapi_open_bus/mobile/find`;

2. 確定請求中的HTTP方法

根據HTTP協議的設計初衷,不同的方法對資源有不同的操作方式:
+ PUT :增
+ DELETE :刪
+ POST:改
+ GET:查

最常用的是GET和POST(實際上GET和POST都能辦到增刪改查)
如果不指定,默認的方法爲GET,當前使用的api接口只支持get請求

let map={
     method:'GET'
};

3. 準備請求中藥傳輸的消息頭

接下來需要設置請求中需要傳輸的消息頭。消息頭分爲兩種,其中一種是協議規定的標準消息頭;另一種是用戶自定義的消息頭。

let privateHeaders={
     'Private-Header':'values1', //自定義消息頭
     //'Content-Type':"text/plain", //設置消息體格式,GET請求不需要設置
     //'User-Agent':'testAgent',// 如果不設置默認爲okhttp/2.5.0
     'apikey':'9dc7ab2f8993b0b215ad8c550e1f4ebe' //百度賬號的apikey
};
map.headers=privateHeaders; //加上自定義消息頭
map.follow=20;//設置允許最大的重定向次數,0不允許重定向
map.timeout=0;//設置超時時間,0代表沒有
map.size=0;//請求迴應中消息體最大允許的長度,0沒有限制

RN支持gzip/deflate格式編碼,不需要對此進行設置。RN收到gzip/deflate格式編碼會自動轉換爲普通格式交給開發者。
消息頭是不區分大小寫的,如果有大寫字母,傳輸的時候回自動轉換爲小寫。
key信息請自己註冊。

4. 準備身份驗證信息

某些Http請求需要加入身份驗證信息,比如上面的apikey,有些時候在需要進行身份驗證的時候需要兩次HTTP請求來完成。

5. 確定是否需要攜帶消息體/參數

如果需要帶消息體,可以通過body配置,GET請求不需要。

map.body=JSON.stringify({
       fistParam:'yourValue',
       secondParam:'yourValue'
});

POST請求參數是放在消息體中,而GET直接拼裝在請求地址後面通過?間隔。

let url=`http://apis.baidu.com/showapi_open_bus/mobile/find`;
let params='num=13126939916';
let requestURL=url+"?"+params;

6. 發出消息

將上述5步聯合起來就可以得到發送HTTP或HTTPS的請求片段。如下:

  componentDidMount() {
        let url=`http://apis.baidu.com/showapi_open_bus/mobile/find`;
        let params='num=13126939916';
        let requestURL=url+"?"+params;
        let map={
          method:'GET'
        };
        let privateHeaders={
          //  'Private-Header':'values1', //自定義消息頭
          //  'Content-Type':"text/plain", //設置消息體格式,GET請求不需要設置
          //  'User-Agent':'testAgent',// 如果不設置默認爲okhttp/2.5.0
            'apikey':'9dc7ab2f8993b0b215ad8c550e1f4ebe'
        };
         map.headers=privateHeaders; //加上自定義消息頭
         map.follow=20;//設置允許最大的重定向次數,0不允許重定向
         map.timeout=0;//設置超時時間,0代表沒有
         map.size=0;//請求迴應中消息體最大允許的長度,0沒有限制
         //map.body='this is body';
        fetch(requestURL,map)
            .then(
                (result)=>{
                    //接受迴應消息處理.
                    console.log(result);
                }
            )
    }

注意事項 解決IOS9以上默認不能訪問http請求

WWDC 15 提出的 ATS (App Transport Security) 是 Apple 在推進網絡通訊安全的一個重要方式。在 iOS 9 和 OS X 10.11 中,默認情況下非 HTTPS 的網絡訪問是被禁止的。當然,因爲這樣的推進影響面非常廣,作爲緩衝,我們可以在 Info.plist 中添加 NSAppTransportSecurity 字典並且將NSAllowsArbitraryLoads 設置爲 YES 來禁用 ATS。

找到info.plist文件添加NSAllowsArbitraryLoads

或者直接在xcode中打開ios項目進行配置。

接收響應

當請求成功,會返回一個存儲有迴應數據的對象

  1. type 字符串類型,記錄請求類型
  2. url 請求地址
  3. status 響應碼 200代表成功
  4. ok 布爾類型,記錄是否成功。

fetch方法

fetch 返回的 then 方法有一個 response 參數,它是一個 Response 實例。 Response 有如下方法:

  • clone() - 複製一份response
  • error() - 返回一個與網絡相關的錯誤
  • redirect() - 返回了一個可以重定向至某URL的response.
  • arrayBuffer() - 返回一個帶有ArrayBuffer的Promise.
  • blob() - 返回一個帶有Blob的Promise.
  • formData() - 返回一個帶有FormData的Promise.
  • json() - 返回一個帶有JSON格式對象的Promise.
  • text() - 返回一個帶有文本的Promise.

下面就是完整的返回json的例子:

fetch(requestURL,map)
     .then((result)=>result.json()) // 返回帶有json格式的Promise
     .catch((error)=>{   // 捕獲錯誤
           console.log(error);  
     })
     .then((responseData)=>{   // 輸出json數據
           console.log(responseData);
     });

完整的例子

    componentDidMount() {
        let url=`http://apis.baidu.com/showapi_open_bus/mobile/find`;
        let params='num=13126939916';
        let requestURL=url+"?"+params;
        let map={
          method:'GET'
        };
        let privateHeaders={
            'apikey':'9dc7ab2f8993b0b215ad8c550e1f4ebe'
        };
         map.headers=privateHeaders; //加上自定義消息頭
         map.follow=20;//設置允許最大的重定向次數,0不允許重定向
         map.timeout=0;//設置超時時間,0代表沒有
         map.size=0;//請求迴應中消息體最大允許的長度,0沒有限制
        fetch(requestURL,map)
            .then((result)=>result.json()) //.json()
            .catch((error)=>{
                console.log(error);
            })
            .then((responseData)=>{
                console.log(responseData);
            });
    }

當然也可以用ES2017的語法:

    async netWork() {
        let url=`http://apis.baidu.com/showapi_open_bus/mobile/find`;
        let params='num=13126939916';
        let requestURL=url+"?"+params;
        try {
            let response = await fetch(requestURL,{
                headers:{
                    'apikey':'9dc7ab2f8993b0b215ad8c550e1f4ebe'
                }
            });
            let responseJson = await response.json();
            console.log(responseJson);
            return responseJson;
        } catch (error) {
            console.error(error);
        }
    }

更多精彩請關注微信公衆賬號likeDev
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章