ReactNative網(wǎng)絡(luò)請求,Promise封裝fetch

React Native中雖然也內(nèi)置了XMLHttpRequest 網(wǎng)絡(luò)請求API(也就是俗稱的ajax),但XMLHttpRequest 是一個設(shè)計粗糙的 API宾濒,不符合職責(zé)分離的原則,配置和調(diào)用方式非吵慈常混亂捞慌,而且基于事件的異步模型寫起來也沒有現(xiàn)代的 Promise 友好耀鸦。而Fetch 的出現(xiàn)就是為了解決 XHR 的問題,所以ReactNative官方推薦使用Fetch API啸澡。http://blog.csdn.net/withings/article/details/71331726

fetch請求示例如下:

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

使用Promise封裝fetch請求

由于在項目中很多地方都需要用到網(wǎng)絡(luò)請求袖订,為了使用上的方便,使用ES6的Promise來封裝fetch網(wǎng)絡(luò)請求嗅虏,代碼如下:

    let common_url = 'http://192.168.1.1:8080/';  //服務(wù)器地址
    let token = '';   
    /**
     * @param {string} url 接口地址
     * @param {string} method 請求方法:GET洛姑、POST,只能大寫
     * @param {JSON} [params=''] body的請求參數(shù)皮服,默認(rèn)為空
     * @return 返回Promise
     */
    function fetchRequest(url, method, params = ''){
        let header = {
            "Content-Type": "application/json;charset=UTF-8",
            "accesstoken":token  //用戶登陸后返回的token楞艾,某些涉及用戶數(shù)據(jù)的接口需要在header中加上token
        };
        console.log('request url:',url,params);  //打印請求參數(shù)
        if(params == ''){   //如果網(wǎng)絡(luò)請求中帶有參數(shù)
            return new Promise(function (resolve, reject) {
                fetch(common_url + url, {
                    method: method,
                    headers: header
                }).then((response) => response.json())
                    .then((responseData) => {
                        console.log('res:',url,responseData);  //網(wǎng)絡(luò)請求成功返回的數(shù)據(jù)
                        resolve(responseData);
                    })
                    .catch( (err) => {
                        console.log('err:',url, err);     //網(wǎng)絡(luò)請求失敗返回的數(shù)據(jù)        
                        reject(err);
                    });
            });
        }else{   //如果網(wǎng)絡(luò)請求中沒有參數(shù)
            return new Promise(function (resolve, reject) {
                fetch(common_url + url, {
                    method: method,
                    headers: header,
                    body:JSON.stringify(params)   //body參數(shù),通常需要轉(zhuǎn)換成字符串后服務(wù)器才能解析
                }).then((response) => response.json())
                    .then((responseData) => {
                        console.log('res:',url, responseData);   //網(wǎng)絡(luò)請求成功返回的數(shù)據(jù)
                        resolve(responseData);
                    })
                    .catch( (err) => {
                        console.log('err:',url, err);   //網(wǎng)絡(luò)請求失敗返回的數(shù)據(jù)  
                        reject(err);
                    });
            });
        }
    }

使用fetch請求龄广,如果服務(wù)器返回的中文出現(xiàn)了亂碼硫眯,則可以在服務(wù)器端設(shè)置如下代碼解決:
produces="text/html;charset=UTF-8"

fetchRequest使用如下:

  • GET請求:
    fetchRequest('app/book','GET')
    .then( res=>{
    //請求成功
    if(res.header.statusCode == 'success'){
    //這里設(shè)定服務(wù)器返回的header中statusCode為success時數(shù)據(jù)返回成功

            }else{
                //服務(wù)器返回異常,設(shè)定服務(wù)器返回的異常信息保存在 header.msgArray[0].desc
                console.log(res.header.msgArray[0].desc);
            }
        }).catch( err=>{ 
            //請求失敗
        })
    

POST請求:

    let params = {
        username:'admin',
        password:'123456'
    }
    fetchRequest('app/signin','POST',params)
        .then( res=>{
            //請求成功
            if(res.header.statusCode == 'success'){
                //這里設(shè)定服務(wù)器返回的header中statusCode為success時數(shù)據(jù)返回成功
     
            }else{
                //服務(wù)器返回異常择同,設(shè)定服務(wù)器返回的異常信息保存在 header.msgArray[0].desc 
                console.log(res.header.msgArray[0].desc);
            }
        }).catch( err=>{ 
            //請求失敗
        })

fetch超時處理

由于原生的Fetch API 并不支持timeout屬性两入,如果項目中需要控制fetch請求的超時時間,可以對fetch請求進一步封裝實現(xiàn)timeout功能敲才,代碼如下:

fetchRequest超時處理封裝

    /**
     * 讓fetch也可以timeout
     *  timeout不是請求連接超時的含義裹纳,它表示請求的response時間择葡,包括請求的連接、服務(wù)器處理及服務(wù)器響應(yīng)回來的時間
     * fetch的timeout即使超時發(fā)生了剃氧,本次請求也不會被abort丟棄掉敏储,它在后臺仍然會發(fā)送到服務(wù)器端,只是本次請求的響應(yīng)內(nèi)容被丟棄而已
     * @param {Promise} fetch_promise    fetch請求返回的Promise
     * @param {number} [timeout=10000]   單位:毫秒朋鞍,這里設(shè)置默認(rèn)超時時間為10秒
     * @return 返回Promise
     */
    function timeout_fetch(fetch_promise,timeout = 10000) {
        let timeout_fn = null; 
     
        //這是一個可以被reject的promise
        let timeout_promise = new Promise(function(resolve, reject) {
            timeout_fn = function() {
                reject('timeout promise');
            };
        });
     
        //這里使用Promise.race虹曙,以最快 resolve 或 reject 的結(jié)果來傳入后續(xù)綁定的回調(diào)
        let abortable_promise = Promise.race([
            fetch_promise,
            timeout_promise
        ]);
     
        setTimeout(function() {
            timeout_fn();
        }, timeout);
     
        return abortable_promise ;
    }
     
    let common_url = 'http://192.168.1.1:8080/';  //服務(wù)器地址
    let token = '';   
    /**
     * @param {string} url 接口地址
     * @param {string} method 請求方法:GET、POST番舆,只能大寫
     * @param {JSON} [params=''] body的請求參數(shù),默認(rèn)為空
     * @return 返回Promise
     */
    function fetchRequest(url, method, params = ''){
        let header = {
            "Content-Type": "application/json;charset=UTF-8",
            "accesstoken":token  //用戶登陸后返回的token矾踱,某些涉及用戶數(shù)據(jù)的接口需要在header中加上token
        };
        console.log('request url:',url,params);  //打印請求參數(shù)
        if(params == ''){   //如果網(wǎng)絡(luò)請求中帶有參數(shù)
            return new Promise(function (resolve, reject) {
                timeout_fetch(fetch(common_url + url, {
                    method: method,
                    headers: header
                })).then((response) => response.json())
                    .then((responseData) => {
                        console.log('res:',url,responseData);  //網(wǎng)絡(luò)請求成功返回的數(shù)據(jù)
                        resolve(responseData);
                    })
                    .catch( (err) => {
                        console.log('err:',url, err);     //網(wǎng)絡(luò)請求失敗返回的數(shù)據(jù)        
                        reject(err);
                    });
            });
        }else{   //如果網(wǎng)絡(luò)請求中沒有參數(shù)
            return new Promise(function (resolve, reject) {
                timeout_fetch(fetch(common_url + url, {
                    method: method,
                    headers: header,
                    body:JSON.stringify(params)   //body參數(shù)恨狈,通常需要轉(zhuǎn)換成字符串后服務(wù)器才能解析
                })).then((response) => response.json())
                    .then((responseData) => {
                        console.log('res:',url, responseData);   //網(wǎng)絡(luò)請求成功返回的數(shù)據(jù)
                        resolve(responseData);
                    })
                    .catch( (err) => {
                        console.log('err:',url, err);   //網(wǎng)絡(luò)請求失敗返回的數(shù)據(jù)  
                        reject(err);
                    });
            });
        }
    }

加入超時處理的fetchRequest網(wǎng)絡(luò)請求的使用方法跟沒加入超時處理一樣。
對于fetch網(wǎng)絡(luò)請求的超時處理的封裝參考下面這篇文章而寫:

[讓fetch也可以timeout]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末呛讲,一起剝皮案震驚了整個濱河市禾怠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贝搁,老刑警劉巖吗氏,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異雷逆,居然都是意外死亡弦讽,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門膀哲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來往产,“玉大人,你說我怎么就攤上這事某宪》麓澹” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵兴喂,是天一觀的道長蔼囊。 經(jīng)常有香客問我,道長衣迷,這世上最難降的妖魔是什么畏鼓? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮壶谒,結(jié)果婚禮上滴肿,老公的妹妹穿的比我還像新娘。我一直安慰自己佃迄,他們只是感情好泼差,可當(dāng)我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布贵少。 她就那樣靜靜地躺著,像睡著了一般堆缘。 火紅的嫁衣襯著肌膚如雪滔灶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天吼肥,我揣著相機與錄音录平,去河邊找鬼。 笑死缀皱,一個胖子當(dāng)著我的面吹牛斗这,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播啤斗,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼表箭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了钮莲?” 一聲冷哼從身側(cè)響起免钻,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎崔拥,沒想到半個月后极舔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡拆魏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了肥卡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溪掀。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖喊递,靈堂內(nèi)的尸體忽然破棺而出骚勘,到底是詐尸還是另有隱情俏讹,我是刑警寧澤泽疆,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布梯浪,位于F島的核電站挂洛,受9級特大地震影響虏劲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜哈肖,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望币狠。 院中可真熱鬧漩绵,春花似錦止吐、人聲如沸碍扔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽菱魔。三九已至澜倦,卻和暖如春藻治,著一層夾襖步出監(jiān)牢的瞬間桩卵,已是汗流浹背雏节。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留寥粹,地道東北人涝涤。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像衫生,于是被迫代替她去往敵國和親罪针。 傳聞我的和親對象是個殘疾皇子泪酱,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,724評論 2 351