React Native 中 fetch的使用心得

最近在搞React Native 開發中,發現fetch與之前瀏覽器中使用XMLHttpRequest有一些差異;
XMLHttpRequest方式的用法,相信你們已經很熟悉了,這裏就不介紹了。javascript

fetch的基本用法GET、POST

先來看看普通的GET的請求:java

// fetch(url,options).then().catch()
// url (required), options (optional)
fetch('http://nero-zou.com/test', {
    method: 'GET'
}).then(function(response) {
    
}).catch(function(err) {
    // Error Handle
});

fetch會返回一個Promise對象,返回的數據會在response參數中;git

請求頭(Request Headers)

經過 new Headers(),你也能夠自由地設置請求頭:github

// 建立一個空的Headers 實例
var headers = new Headers();

// 添加 headers
headers.append('Content-Type', 'text/plain');
headers.append('X-My-Custom-Header', 'CustomValue');

// 檢測、獲取、設置 header
headers.has('Content-Type'); // true
headers.get('Content-Type'); // "text/plain"
headers.set('Content-Type', 'application/json');

// 刪除一個 header
headers.delete('X-My-Custom-Header');

// 建立時帶上參數
var headers = new Headers({
    'Content-Type': 'text/plain',
    'X-My-Custom-Header': 'CustomValue'
});

你能夠使用append, has, get, set, 和delete去修改request headers. Headers與Request的組合是這樣的:express

var request = new Request('http://ner-zou.com/test', {
    headers: new Headers({
        'Content-Type': 'text/plain'
    })
});

fetch(request).then(function() { /* handle response */ });

響應(Response)

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

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

下面看看fetch如何接受服務器端返回的JSON數據:api

fetch('http://nero-zou.com/test.json').then(function(response) { 
    return response.json();// 轉換爲JSON
}).then(function(data) {
    console.log(data); // data 就是一個JavaScript object
});

再加上一些錯誤處理:瀏覽器

fetch('http://nero-zou.com/test.json')
    .then((response) => {
        if (response.ok) {
            return response.json()
        } else {
            console.error('服務器繁忙,請稍後再試;\r\nCode:' + response.status)
        }
    })
    .then((data) => {
        console.log(data)
    })
    .catch((err)=> {
        console.error(err)
    })

response.ok會將40四、500等這些請求錯誤給過濾掉;服務器

GET請求帶上參數

官方推薦了一種寫法:網絡

var url = new URL("https://geo.example.org/api"),
    params = {lat:35.696233, long:139.570431}
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]))
fetch(url).then(/* … */)

可是URL這個方法,在React Native 中並無實現,那麼就只能咱們本身來拼接url了,
這裏咱們對 GET請求封裝一個方法:

/**
 * 基於 fetch 封裝的 GET請求
 * @param url
 * @returns {Promise}
 */
export function R_GET(url, params) {
    if (params) {
        let paramsArray = []
        Object.keys(params).forEach(key => paramsArray.push(key + '=' + encodeURIComponent(params[key])))
        if (url.search(/\?/) === -1) {
            url += '?' + paramsArray.join('&')
        } else {
            url += '&' + paramsArray.join('&')
        }
    }
    return new Promise(function (resolve, reject) {
        fetch(url)
            .then((response) => {
                if (response.ok) {
                    return response.json()
                } else {
                    reject('服務器繁忙,請稍後再試;\r\nCode:' + response.status)
                }
            })
            .then((response) => {
                if (response && response.error_code === 0) {
                    resolve(response)//response.error_code 是與服務器端的約定,非0就是錯誤
                } else {
                    reject(response.message)//response.message也是與服務器端的約定,error_code !==0 就須要返回message
                }
            })
            .catch((err)=> {
                reject(_parseErrorMsg(err))
            })
    })
}

在服務器端(Express.js)中能夠這麼接收參數

//假如在客戶端這麼請求的話
//R_GET('http://nero-zou.com/test',{name:nero})
//等同於這樣 fetch('/test?name=nero')


//... 
router.get('/test', function (req, res) {
    res.send({
        error_code: 0,
        data: {name: req.query.name},//這裏的req.query.name 就是nero了
        message: 'success'
    });
});

POST數據給服務器

JSON格式數據

客戶端能夠這麼寫:

fetch('http://nero-zou.com/test', {
    method: 'post',
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json' //記得加上這行,否則bodyParser.json() 會識別不了
    },
    body: JSON.stringify({
        name: "nero",
        email: "Nero@Nero-zou.com"
    })
});

在服務器端(Express.js)中能夠這麼接收數據

//...
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
//...

//... 省略其餘無關代碼
router.post('/test', function (req, res) {
    res.send({
        error_code: 0,
        data: req.body,//把發過來的數據原封不動返回回去,這裏只是舉例
        message: 'success'
    });
});

URLSearchParams 方式

fetch('/test', {
    method: 'POST',
    headers: {
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
    },
    body: "name=nero&email=Nero@Nero-zou.com"
})

一些參考文章:

相關文章
相關標籤/搜索