react-native fetch的具體使用方法
在前端快速發(fā)展地過程中,為了契合更好的設(shè)計(jì)模式,產(chǎn)生了 fetch 框架,此文將簡(jiǎn)要介紹下 fetch 的基本使用。
在 AJAX 時(shí)代,進(jìn)行請(qǐng)求 API 等網(wǎng)絡(luò)請(qǐng)求都是通過 XMLHttpRequest 或者封裝后的框架進(jìn)行網(wǎng)絡(luò)請(qǐng)求。
現(xiàn)在產(chǎn)生的 fetch 框架簡(jiǎn)直就是為了提供更加強(qiáng)大、高效的網(wǎng)絡(luò)請(qǐng)求而生,雖然在目前會(huì)有一點(diǎn)瀏覽器兼容的問題,但是當(dāng)我們進(jìn)行 Hybrid App 開發(fā)的時(shí)候,如我之前介紹的Ionic 和React Native,都可以使用 fetch 進(jìn)行完美的網(wǎng)絡(luò)請(qǐng)求。
fetch 初體驗(yàn)
在 Chrome 瀏覽器中已經(jīng)全局支持了 fetch 函數(shù),打開調(diào)試工具,在 Console 中可以進(jìn)行初體驗(yàn)。先不考慮跨域請(qǐng)求的使用方法,我們先請(qǐng)求同域的資源,如在我的博客頁面中,打開 Console 進(jìn)行如下請(qǐng)求。
fetch("http://blog.parryqiu.com").then(function(response){console.log(response)})
返回的數(shù)據(jù):

這樣就很快速地完成了一次網(wǎng)絡(luò)請(qǐng)求,我們發(fā)現(xiàn)返回的數(shù)據(jù)也比之前的 XMLHttpRequest 豐富、易用的多。
關(guān)于 fetch 標(biāo)準(zhǔn)概覽
雖然 fetch 還不是作為一個(gè)穩(wěn)定的標(biāo)準(zhǔn)發(fā)布,但是在其一直迭代更新的 標(biāo)準(zhǔn)描述 中,我們發(fā)現(xiàn)已經(jīng)包含了很多的好東西。
fetch 支持了大部分常用的 HTTP 的請(qǐng)求以及和 HTTP 標(biāo)準(zhǔn)的兼容,如 HTTP Method,HTTP Headers,Request,Response。
fetch 的使用
fetch的入口函數(shù)定義在node_modules/whatwg-fetch.js文件中,如下
self.fetch = function (input, init) {
return new Promise(function (resolve, reject) {
var request = new Request(input, init)
var xhr = new XMLHttpRequest()
xhr.onload = function () {
var options = {
status: xhr.status,
statusText: xhr.statusText,
headers: parseHeaders(xhr.getAllResponseHeaders() || '')
}
options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
var body = 'response' in xhr ? xhr.response : xhr.responseText
resolve(new Response(body, options))
}
xhr.onerror = function () {
reject(new TypeError('Network request failed'))
}
xhr.ontimeout = function () {
reject(new TypeError('Network request failed888888888888'))
}
xhr.open(request.method, request.url, true)
if (request.credentials === 'include') {
xhr.withCredentials = true
}
if ('responseType' in xhr && support.blob) {
xhr.responseType = 'blob'
}
request.headers.forEach(function (value, name) {
xhr.setRequestHeader(name, value)
})
xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
})
}
該函數(shù)在Network/fetch.js中被導(dǎo)出,最終在initializeCore.js中被注冊(cè)為global的屬性變?yōu)槿趾瘮?shù)。fetch返回的是一個(gè)Promise。
跟隨方法走向,依次調(diào)用的是XMLHttpRequest.js的send -> RCTNetworking.ios.js的sendRequest -> 最終調(diào)到原生端RCTNetworking.mm的sendRequest方法。
相關(guān)問題點(diǎn):
1、為何fetch函數(shù)無法設(shè)置timeout?
為了設(shè)置fetch的timeout,我會(huì)如下定義一個(gè)函數(shù)
_timeout_fetch(fetch_promise, timeout = 15000) {
let timeout_promise = new Promise(function (resolve, reject) {
setTimeout(() => {
reject('timeout promise');
}, timeout)
});
return Promise.race([
fetch_promise,
timeout_promise
]);
}
然后如下調(diào)用
this._timeout_fetch(
fetch(url, requestParams)
.then(response => response.json())
.then(responseData => {
resolve(responseData);
})
.catch(error => {
reject(error);
})
)
先定義一個(gè)Promise,其在超時(shí)時(shí)間結(jié)束后reject。將這個(gè)Promise和fetch合并到Promise.race中,則一旦這兩個(gè)請(qǐng)求誰先執(zhí)行,另外一個(gè)會(huì)被舍棄。這樣完成超時(shí)時(shí)間的設(shè)置。
但是查看源碼發(fā)現(xiàn)oc中是有超時(shí)時(shí)間設(shè)置這個(gè)選項(xiàng)的,且js和oc通信時(shí)也傳了這個(gè)參數(shù),問題是出在入口函數(shù)fetch處,只需要在上面fetch方法中添加上如下
xhr.timeout = init.timeout || 0;
就可以在請(qǐng)求參數(shù)中設(shè)置超時(shí)時(shí)間了,如
let requestParams = {
method: method,
header: {
"Content-Type": "application/json;charset=UTF-8",
},
timeout: 1000
};
2、fetch函數(shù)為何無法cancel?
fetch在原生端是NSURLSessionDataTask發(fā)的請(qǐng)求,這個(gè)是可取消的。在js端的XMLHttpRequest.js中也發(fā)現(xiàn)了abort方法,調(diào)用能夠取消當(dāng)前網(wǎng)絡(luò)請(qǐng)求。問題出在了fetch的接口函數(shù)。
首先,要想請(qǐng)求能夠取消,得拿到當(dāng)前請(qǐng)求對(duì)應(yīng)的requestId。請(qǐng)求的執(zhí)行順序是js端發(fā)起 -> OC生成Request,得到requestId,利用NSURLSessionDataTask發(fā)起請(qǐng)求 -> 將requestId通過回調(diào)的形式傳回給js端,js若想取消該請(qǐng)求,執(zhí)行abort方法即可。
要想fetch函數(shù)能夠執(zhí)行cancel,只需該方法將XMLHttpRequest對(duì)象返回即可。但是那樣,就不再是一個(gè)Promise了。
也可以將cancel方法綁定到返回的Promise對(duì)象上,修改方法如下
self.fetch = function (input, init) {
var xhr = new XMLHttpRequest()
let p = new Promise(function (resolve, reject) {
var request = new Request(input, init)
// xhr的各種設(shè)置,回調(diào)等
})
p.cancel = () => {
xhr.abort()
}
return p;
}
如此,調(diào)用的時(shí)候就比較惡習(xí)了,要如下
let promise = fetch(url);
promise.then(res => {
}).then(res => {
}).catch(err => {
})
promise.cancel() // 取消該網(wǎng)絡(luò)請(qǐng)求
不能fecth().then().then()的模式調(diào)用,因?yàn)檫@樣會(huì)導(dǎo)致返回的那個(gè)Promise不再是上面綁定了cancel的那個(gè)Promise。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
react中axios結(jié)合后端實(shí)現(xiàn)GET和POST請(qǐng)求方式
這篇文章主要介紹了react中axios結(jié)合后端實(shí)現(xiàn)GET和POST請(qǐng)求方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02
react項(xiàng)目中使用react-dnd實(shí)現(xiàn)列表的拖拽排序功能
這篇文章主要介紹了react項(xiàng)目中使用react-dnd實(shí)現(xiàn)列表的拖拽排序,本文結(jié)合實(shí)例代碼講解react-dnd是如何實(shí)現(xiàn),代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-02-02
React?Hooks項(xiàng)目實(shí)戰(zhàn)
React?Hooks是React?16.8版本引入的新特性,它使得在函數(shù)組件中也能夠使用狀態(tài)(state)和其他React特性,本文就來詳細(xì)介紹一下React?Hooks項(xiàng)目實(shí)戰(zhàn),感興趣的可以了解一下2023-11-11
react-three-fiber實(shí)現(xiàn)炫酷3D粒子效果首頁
這篇文章主要介紹了react-three-fiber實(shí)現(xiàn)3D粒子效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
react18中react-redux狀態(tài)管理的實(shí)現(xiàn)
本文主要介紹了react18中react-redux狀態(tài)管理的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05

