Fetch的使用及兼容ie的處理


 Fetch

作為一個與時俱進的前端,Fetch當然應該有所了解和涉獵。如果你沒有聽說過Fetch,那么ajax應該不陌生吧。Fetch相當於是一個新版本的Ajax,雖然現在我們常常使用的仍是ajax,但是fetch已經在漸漸地撼動ajax的地位。在最近的項目中,為了更新一下技術棧,所以使用了fetch。所以寫一篇文章記錄一下fetch相關的內容。

 

先說一下fetch的優點吧,首先ajax最遭人詬病的就是回調地獄了,也就是比如說如果你要發送一個Ajax請求,但是請求的參數卻需要上一個ajax來返回。那么這次的請求就需要放在上一次請求的回調函數中,如果只有兩個請求還好,要是多個請求那么代碼不僅可讀性差,維護起來也十分的困難。在Es6中我們可以使用promise來解決回調地獄的問題,實際上fetch的解決方式就是類似於使用promise的ajax,它的使用方式也類似於promise,使用起來代碼的可讀性可維護性都變得更好了。

 

如果不了解promise的童鞋可以去看es6的文檔,或者看相關的教程,這里為了直奔主題就不講解promise了

先看一下MDN的官方文檔

 

這是fetch的基本用法,第一個參數是url也就是你請求的地址,第二個參數接受一個配置對象,該對象的具體屬性以及可以設置的值已經在上圖展示。

具體參數配置如下:

 

一般來說使用fetch會用url加上配置對象的方式來發送請求,不過你也可以使用request構造函數實例化一個request對象作為參數傳入

 

在這里主要講一下使用配置對象的方式來使用fetch

 

首先要進行請求,我們需要一個后台接口,由於現如今開發模式基本上都是前后分離,所以我們的fetch請求不可避免的要涉及到跨域問題。

 

在下面的例子中,我使用的是nodejs,和express搭建的后台。

 

由於我使用的是項目的后台只是在app.js中加了一個測試接口所以就不貼出完整的app.js的代碼了

 

我使用的后台接口代碼如下

app.all('/Api', function(req, res, next) {
// 打印前端的信息 console.log(req.body);
  console.log(req.cookies);
  console.log(req.get('Token'));
res.header(
"Access-Control-Allow-Origin", "http://localhost:63342"); // 設置請求的來源的域 res.header("Access-Control-Allow-Headers", "Token,x-token,Content-Type"); // 設置允許的自定義頭部 res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS"); // 設置允許的請求的類型 res.header("Access-Control-Allow-Credentials",true); // 設置是否允許跨域請求攜帶cookie等瀏覽器信息 res.header("X-Powered-By",'lhy'); res.header("Content-Type", "application/json;charset=utf-8"); // 設置返回的數據類型,這里設置為返回的json類型的數據 res.send({meta:{token:"123",code:1}}); // 發送響應信息 });

 

前端使用fetch代碼如下

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>Fetch</title>
    <meta name="Description" content=""/>
    <meta name="Author" content="lhy"/>
</head>
<body>
<p></p>

<script>
    let options = {
        method:"post",
        body:JSON.stringify({name:"lhy",content:"hello"}), // 這里傳入的數據類型必須和下面content-type的類型一致
        cache:'reload', // 表示請求時忽略http緩存,但是請求完成后會刷新http緩存
        credentials:'include', // 表示請求攜帶cookie等信息
        headers:{
            'Token':"lhytest", // 用於設置請求頭
            'content-type': 'application/json' // 設置發送的數據類型
        }
    };
    fetch('http://localhost/Api',options).then(function (response) {
        return response.json()
    }).then(function (data) {
        console.log(data);
        document.getElementsByTagName('p')[0].innerText = data.meta.token;
    }).catch(function (error) {
        console.log(error);
    })
</script>
</body>
</html>

 

 

PS:剛才在后台設置的允許跨域的源我們可以在瀏覽器調試窗口看到,而且如果你的html是本地環境打開Origin的值會為null,我這里是使用的webstrom打開的

 

 

 現在我們來看看結果

可以看到我們已經成功地拿到了后台地數據,我們再去看看后台是否也能拿到我傳遞的參數,以及cookie的信息

 

 

 PS:你設置的自定義頭部在瀏覽器調試窗口無法看到,因為瀏覽器顯示的頭只顯示它默認規定的請求頭信息,如果你希望在瀏覽器窗口看到就需要將它暴露出去,這里不要再細說

 

Fetch的兼容

在上面我們可以看到,fetch還是十分方便強大的,所有的新的這些好用的技術往往都有一個限制那就是兼容問題

我們先看一下原生的fetch的兼容性如何

這么好用的東西,ie竟然完全不支持(垃圾ie毀我青春!!)

 

沒辦法,這可不是低版本ie不兼容,而是ie完全不兼容,雖然現在ie的市場份額在逐年下降,但是其用戶群體還是十分龐大的,而不巧的是這次的項目要求兼容到ie8

 

這不是為難我胖虎嗎?我又不想舍棄好用的fetch,沒辦法那就自己封裝一個ie版本的fetch吧。

 

封裝一個ie版本的fetch,首先我們要了解這個fetch到底包含了些什么,作為一個精致的前端,我可不想直接調用fetch時檢測一下window下有沒有這個函數,沒有就用ajax的粗陋的方式。

 

所以就有了這篇文章的后半部分。

 

我們先來看看MDN的fetch的使用模塊下有些什么東西

 

所以我們要重新封裝一下 Body,Headers,Request,Response

 

本人很菜,下面的封裝方式全是我自己的看法,很有可能並不是fetch的內部實現方式,特此聲明。

 

參考文章:https://segmentfault.com/a/1190000006220369

 

主要思路:

 

檢測瀏覽器版本,是ie10,11使用XMLHttpRequest進行請求

 

ie8,9 使用XDomainRequest

 

ie8以下使用ActiveXObject進行請求

(function webpackUniversalModuleDefinition(root, factory) {
    if (typeof exports === 'object' && typeof module === 'object')
        module.exports = factory();
    else if (typeof define === 'function' && define.amd)
        define([], factory);
    else if (typeof exports === 'object')
        exports["fetch"] = factory();
    else
        root["fetch"] = factory();
})(this, function () {
    return /******/ (function (modules) { // webpackBootstrap
        /******/     // The module cache
        /******/
        var installedModules = {};

        /******/     // The require function
        /******/
        function __webpack_require__(moduleId) {

            /******/         // Check if module is in cache
            /******/
            if (installedModules[moduleId])
            /******/            return installedModules[moduleId].exports;

            /******/         // Create a new module (and put it into the cache)
            /******/
            var module = installedModules[moduleId] = {
                /******/            exports: {},
                /******/            id: moduleId,
                /******/            loaded: false
                /******/
            };

            /******/         // Execute the module function
            /******/
            modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

            /******/         // Flag the module as loaded
            /******/
            module.loaded = true;

            /******/         // Return the exports of the module
            /******/
            return module.exports;
            /******/
        }


        /******/     // expose the modules object (__webpack_modules__)
        /******/
        __webpack_require__.m = modules;

        /******/     // expose the module cache
        /******/
        __webpack_require__.c = installedModules;

        /******/     // __webpack_public_path__
        /******/
        __webpack_require__.p = "";

        /******/     // Load entry module and return exports
        /******/
        return __webpack_require__(0);
        /******/
    })
    /************************************************************************/
    /******/([
        /* 0 */
        /***/ function (module, exports, __webpack_require__) {

            var Request = __webpack_require__(1)
            var Response = __webpack_require__(5)
            var Headers = __webpack_require__(2)
            var Transport = __webpack_require__(6)

            if (![].forEach) {
                Array.prototype.forEach = function (fn, scope) {
                    'use strict'
                    var i, len
                    for (i = 0, len = this.length; i < len; ++i) {
                        if (i in this) {
                            fn.call(scope, this[i], i, this)
                        }
                    }
                }
            }
            // 用於讀取響應頭信息
            if (!'lhy'.trim) {
                var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g
                String.prototype.trim = function () {
                    return this.replace(rtrim, '')
                }
            }
            function headers(xhr) {
                var head = new Headers()
                if (xhr.getAllResponseHeaders) {
                    var headerStr = xhr.getAllResponseHeaders() || ''
                    if (/\S/.test(headerStr)) {
                        //http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders-method
                        var headerPairs = headerStr.split('\u000d\u000a');
                        for (var i = 0; i < headerPairs.length; i++) {
                            var headerPair = headerPairs[i];
                            // 讀取header的信息
                            var index = headerPair.indexOf('\u003a\u0020')
                            if (index > 0) {
                                var key = headerPair.substring(0, index).trim()
                                var value = headerPair.substring(index + 2).trim()
                                head.append(key, value)
                            }
                        }
                    }
                }
                return head
            }

            function fetch(input, init) {
                return new Promise(function (resolve, reject) {
                    var request
                    if (!init && (init instanceof Request)) {
                        request = input
                    } else {
                        request = new Request(input, init)
                    }

                    var msie = 11
                    // 用於判斷是否為ie
                    if (window.VBArray) {
                        // 返回瀏覽器渲染文檔模式
                        msie = document.documentMode || (window.XMLHttpRequest ? 7 : 6)
                    }

                    if (msie > 7) {
                        var xhr = new Transport(request)

                        function responseURL() {
                            if ('responseURL' in xhr) {
                                return xhr.responseURL
                            }

                            return
                        }

                        xhr.on('load', function (event) {
                            var options = {
                                status: event.status || 200,
                                statusText: event.statusText || '',
                                headers: headers(event),
                                url: responseURL()
                            }
                            var body = 'response' in event ? event.response : event.responseText
                            resolve(new Response(body, options))
                        })
                        xhr.on('error', function () {
                            reject(new TypeError('Network request failed'))
                        })
                        xhr.on('timeout', function () {
                            reject(new TypeError('Network request timeout'))
                        })
                        xhr.open(request.method, request.url, true)

                        request.headers.forEach(function (value, name) {
                            xhr.setRequestHeader(name, value)
                        })
                        xhr.send(typeof request._body === 'undefined' ? null : request._body)
                    } else {
                        var xhr = new ActiveXObject('Microsoft.XMLHTTP')
                        xhr.onreadystatechange = function () {
                            if (xhr.readyState === 4) {
                                var options = {
                                    status: xhr.status || 200,
                                    statusText: xhr.statusText || '',
                                    headers: headers(xhr),
                                    url: responseURL()
                                }
                                var body = 'response' in xhr ? xhr.response : xhr.responseText
                                resolve(new Response(body, options))
                            }
                        }
                        xhr.open(request.method, request.url, true)
                        xhr.send(typeof request._body === 'undefined' ? null : request._body)
                    }
                })
            }

            function notFunc(a) {
                return !/\scode\]\s+\}$/.test(a)
            }

            if (notFunc(window.fetch)) {
                window.fetch = fetch
            }
            if (typeof avalon === 'function') {
                avalon.fetch = fetch
            }
            module.exports = fetch

            /***/
        },
        /* 1 */
        /***/ function (module, exports, __webpack_require__) {

            var Headers = __webpack_require__(2)
            var Body = __webpack_require__(4)

            // 自定義Request函數
            function Request(input, options) {
                options = options || {}
                var body = options.body
                // 用於判斷函數接受的參數是否為自定義的Request對象 即判斷input是否由Request創建
                if (input instanceof Request) {
                    // 判斷body是否已被使用
                    if (input.bodyUsed) {
                        throw new TypeError('Already read')
                    }
                    this.url = input.url
                    this.credentials = input.credentials
                    if (!options.headers) {
                        var h = this.headers = new Headers(input.headers)
                        if (!h.map['x-requested-with']) {
                            h.set('X-Requested-With', 'XMLHttpRequest')
                        }
                    }
                    this.method = input.method
                    this.mode = input.mode
                    if (!body) {
                        body = input._body
                        input.bodyUsed = true
                    }
                } else {
                    // 如果input不是由Request創建的自定義Request對象 則input為url參數
                    this.url = input
                }
                // 優先判斷option中是否設置了相關選項,再判斷credentials自定義request對象的相關屬性,如果都沒有默認為‘omit’
                this.credentials = options.credentials || this.credentials || 'omit'
                // 判斷參數是否設置了header的相關選項
                if (options.headers || !this.headers) {
                    this.headers = new Headers(options.headers)
                }
                this.method = (options.method || this.method || 'GET').toUpperCase()
                this.mode = options.mode || this.mode || null
                this.referrer = null

                // 如果是head請求卻攜帶了請求體,拋出錯誤
                if ( this.method === 'HEAD' && body) {
                    throw new TypeError('Body not allowed for HEAD requests')
                }else if(this.method === 'GET' && body){
                    var Obody = JSON.parse(body)
                    var str = ''
                    for (var name in Obody) {
                        if(Obody.hasOwnProperty(name)){
                            str = str? str + '&' + name + '=' + Obody[name] : str +  name + '=' + Obody[name]
                        }
                    }
                    this.url += '?' + str
                    body = null
                }
                this._initBody(body)
            }

            Request.prototype.clone = function () {
                return new Request(this)
            }

            var F = function () {
            }
            F.prototype = Body.prototype
            Request.prototype = new F()

            module.exports = Request

            /***/
        },
        /* 2 */
        /***/ function (module, exports, __webpack_require__) {

            var support = __webpack_require__(3)

            // 自定義Header
            function Headers(headers) {
                this.map = {}
                if (headers instanceof Headers) {
                    headers.forEach(function (value, name) {
                        this.append(name, value)
                    }, this)

                } else if (headers) {
                    for (var name in headers) {
                        if (headers.hasOwnProperty(name)) {
                            this.append(name, headers[name])
                        }
                    }

                }
            }

            // 向header對象中的map 添加鍵值對
            Headers.prototype.append = function (name, value) {
                name = normalizeName(name)
                value = normalizeValue(value)
                var list = this.map[name]
                if (!list) {
                    list = []
                    this.map[name] = list
                }
                list.push(value)
            }

            // 定義header上的delet方法用於刪除鍵值對
            Headers.prototype['delete'] = function (name) {
                delete this.map[normalizeName(name)]
            }

            // 用於獲取header對象上的某個鍵的第一個值
            Headers.prototype.get = function (name) {
                var values = this.map[normalizeName(name)]
                return values ? values[0] : null
            }

            // 用於獲取header對象上某個鍵的所有值
            Headers.prototype.getAll = function (name) {
                return this.map[normalizeName(name)] || []
            }

            // 判斷該header對象是否擁有某個屬性
            Headers.prototype.has = function (name) {
                return this.map.hasOwnProperty(normalizeName(name))
            }

            // 用於設置該header對象上的值
            Headers.prototype.set = function (name, value) {
                this.map[normalizeName(name)] = [normalizeValue(value)]
            }

            // 為了在低版本瀏覽器使用,定義forEach以遍歷
            Headers.prototype.forEach = function (callback, thisArg) {
                for (var name in this.map) {
                    if (this.map.hasOwnProperty(name)) {
                        this.map[name].forEach(function (value) {
                            callback.call(thisArg, value, name, this)
                        }, this)
                    }
                }
            }

            // 返回header對象的可枚舉屬性及函數名
            Headers.prototype.keys = function () {
                var items = []
                this.forEach(function (value, name) {
                    items.push(name)
                })
                return items
            }
            // 返回header對象的所有可枚舉的值
            Headers.prototype.values = function () {
                var items = []
                this.forEach(function (value) {
                    items.push(value)
                })
                return items
            }
            //  修改迭代器的方法
            Headers.prototype.entries = function () {
                var items = []
                this.forEach(function (value, name) {
                    items.push([name, value])
                })
                return items
            }
            // 判斷是否支持迭代器
            if (support.iterable) {
                // 如果支持 則讓header的iterable為上方的entries函數
                Headers.prototype[Symbol.iterator] = Headers.prototype.entries
            }

            // 判斷頭名是否合法,只要不包含特殊字符就返回 頭名的字符串
            function normalizeName(name) {
                if (typeof name !== 'string') {
                    name = String(name)
                }
                if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
                    throw new TypeError('Invalid character in header field name')
                }
                return name.toLowerCase()
            }

            // 將值轉為字符串
            function normalizeValue(value) {
                if (typeof value !== 'string') {
                    value = String(value)
                }
                return value
            }

            module.exports = Headers

            /***/
        },
        /* 3 */
        /**
         * 該函數用於判斷瀏覽器是否支持
         * */ function (module, exports) {

            module.exports = {
                searchParams: 'URLSearchParams' in window,
                iterable: 'Symbol' in window && 'iterator' in window,
                blob: 'FileReader' in window && 'Blob' in window && (function () {
                    try {
                        new Blob()
                        return true
                    } catch (e) {
                        return false
                    }
                })(),
                formData: 'FormData' in window,
                arrayBuffer: 'ArrayBuffer' in window
            }


            /***/
        },
        /* 4 */
        /***/ function (module, exports, __webpack_require__) {

            var support = __webpack_require__(3)

            // 用於創建body對象
            function Body() {
                this.bodyUsed = false
            }

            var p = Body.prototype

            'text,blob,formData,json,arrayBuffer'.replace(/\w+/g, function (method) {
                p[method] = function () {
                    return consumeBody(this).then(function (body) {
                        return convertBody(body, method)
                    })
                }
            })

            // 初始化請求的頭部
            p._initBody = function (body) {
                this._body = body
                if (!this.headers.get('content-type')) {
                    var a = bodyType(body)
                    switch (a) {
                        case 'text':
                            this.headers.set('content-type', 'text/plain;charset=UTF-8')
                            break
                        case 'blob':
                            if (body && body.type) {
                                this.headers.set('content-type', body.type)
                            }
                            break
                        case 'searchParams':
                            this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')
                            break
                    }
                }
            }

            // 判斷Body是否已被使用
            function consumeBody(body) {
                if (body.bodyUsed) {
                    return Promise.reject(new TypeError('Already read'))
                } else {
                    body.bodyUsed = true
                    return Promise.resolve(body._body)
                }
            }

            // 用於處理返回的response對象body的數據
            function convertBody(body, to) {
                var from = bodyType(body)
                if (body === null || body === void 0 || !from || from === to) {
                    return Promise.resolve(body)
                } else if (map[to] && map[to][from]) {
                    return map[to][from](body)
                } else {
                    return Promise.reject(new Error('Convertion from ' + from + ' to ' + to + ' not supported'))
                }
            }

            // 定義對各種類型數據的處理方法
            var map = {
                text: {
                    json: function (body) {//json --> text
                        return Promise.resolve(JSON.stringify(body))
                    },
                    blob: function (body) {//blob --> text
                        return blob2text(body)
                    },
                    searchParams: function (body) {//searchParams --> text
                        return Promise.resolve(body.toString())
                    }
                },
                json: {
                    text: function (body) {//text --> json
                        return Promise.resolve(parseJSON(body))
                    },
                    blob: function (body) {//blob --> json
                        return blob2text(body).then(parseJSON)
                    }
                },
                formData: {
                    text: function (body) {//text --> formData
                        return text2formData(body)
                    }
                },
                blob: {
                    text: function (body) {//json --> blob
                        return Promise.resolve(new Blob([body]))
                    },
                    json: function (body) {//json --> blob
                        return Promise.resolve(new Blob([JSON.stringify(body)]))
                    }
                },
                arrayBuffer: {
                    blob: function (body) {
                        return blob2ArrayBuffer(body)
                    }
                }
            }

            // 用於返回body攜帶的數據類型
            function bodyType(body) {
                if (typeof body === 'string') {
                    return 'text'
                } else if (support.blob && (body instanceof Blob)) {
                    return 'blob'
                } else if (support.formData && (body instanceof FormData)) {
                    return 'formData'
                } else if (support.searchParams && (body instanceof URLSearchParams)) {
                    return 'searchParams'
                } else if (body && typeof body === 'object') {
                    return 'json'
                } else {
                    return null
                }
            }

            // 用於低版本瀏覽器的reader
            function reader2Promise(reader) {
                return new Promise(function (resolve, reject) {
                    reader.onload = function () {
                        resolve(reader.result)
                    }
                    reader.onerror = function () {
                        reject(reader.error)
                    }
                })
            }

            /*
            模擬下列函數 用於處理各種類型的返回值數據
             readAsBinaryString(File|Blob)
             readAsText(File|Blob [, encoding])
             readAsDataURL(File|Blob)
             readAsArrayBuffer(File|Blob)
             */
            function text2formData(body) {
                var form = new FormData()
                body.trim().split('&').forEach(function (bytes) {
                    if (bytes) {
                        var split = bytes.split('=')
                        var name = split.shift().replace(/\+/g, ' ')
                        var value = split.join('=').replace(/\+/g, ' ')
                        form.append(decodeURIComponent(name), decodeURIComponent(value))
                    }
                })
                return Promise.resolve(form)
            }

            function blob2ArrayBuffer(blob) {
                var reader = new FileReader()
                reader.readAsArrayBuffer(blob)
                return reader2Promise(reader)
            }

            function blob2text(blob) {
                var reader = new FileReader()
                reader.readAsText(blob)
                return reader2Promise(reader)
            }


            function parseJSON(body) {
                try {
                    return JSON.parse(body)
                } catch (ex) {
                    throw 'Invalid JSON'
                }
            }

            module.exports = Body

            /***/
        },
        /* 5 */
        /***/ function (module, exports, __webpack_require__) {

            var Headers = __webpack_require__(2)
            var Body = __webpack_require__(4)
            // 用於返回response對象 即請求到的數據

            function Response(bodyInit, options) {
                if (!options) {
                    options = {}
                }

                this.type = 'default'
                // status
                this.status = options.status
                // ok
                this.ok = this.status >= 200 && this.status < 300
                // status
                this.statusText = options.statusText
                this.headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers)
                this.url = options.url || ''
                this._initBody(bodyInit)
            }

            var F = function () {
            }
            F.prototype = Body.prototype
            Response.prototype = new F()

            Response.prototype.clone = function () {
                return new Response(this._bodyInit, {
                    status: this.status,
                    statusText: this.statusText,
                    headers: new Headers(this.headers),
                    url: this.url
                })
            }

            Response.error = function () {
                var response = new Response(null, {status: 0, statusText: ''})
                response.type = 'error'
                return response
            }

            // 重定向狀態碼
            var redirectStatuses = [301, 302, 303, 307, 308]

            Response.redirect = function (url, status) {
                if (redirectStatuses.indexOf(status) === -1) {
                    throw new RangeError('Invalid status code')
                }

                return new Response(null, {status: status, headers: {location: url}})
            }

            module.exports = Response

            /***/
        },
        /* 6 */
        /***/ function (module, exports, __webpack_require__) {
            // ajax 非低版本ie及谷歌火狐使用XMLHttpRequest
            //ie 8 - 9 使用XDomainRequest
            //低版本ie 使用 ActiveXObject('Microsoft.XMLHTTP')
            var AXO = __webpack_require__(7)
            var JSONP = __webpack_require__(8)
            var XDR = __webpack_require__(9)
            var XHR = __webpack_require__(10)
            var msie = 0
            if (window.VBArray) {
                msie = document.documentMode || (window.XMLHttpRequest ? 7 : 6)
            }

            function Transport(request) {
                if (msie === 8 || msie === 9) {
                    this.core = new XDR(request)
                } else if (!msie || msie > 9) {
                    this.core = new XHR(request)
                }
            }

            var p = Transport.prototype

            p.on = function (type, fn) {
                this.core.on(type, fn)
            }


            p.setRequestHeader = function (a, b) {
                if (this.core.setRequestHeader) {
                    this.core.setRequestHeader(a, b)
                }
            }

            p.open = function (a, b, c, d, e) {
                if (this.core.open) {
                    this.core.open(a, b, c, d, e)
                }
            }

            p.send = function (a) {
                if (this.core.send) {
                    this.core.send(a)
                }
            }

            p.abort = function () {
                if (this.core.abort) {
                    this.core.abort()
                }
            }

            module.exports = Transport

            /***/
        },
        /* 7 */
        /***/ function (module, exports) {

            module.exports = function AXO(opts) {

                var xhr = new ActiveXObject('Microsoft.XMLHTTP')

                // xhr.onreadystatechange = function () {
                //     if (xhr.readyState === 4) {
                //         if (/^2\d\d|1224/.test(xhr.status)) {
                //             events['load'] && events['load'](xhr)
                //         } else {
                //             events['error'] && events['error']()
                //         }
                //     }
                // }
                //
                // var events = {}
                // Object.defineProperty(xhr,on,)
                // xhr.on = function (type, fn) {
                //     events[type] = fn
                // }

                // if (opts.timeout === 'number') {
                //     setTimeout(function () {
                //         events['timeout'] && events['timeout']()
                //         xhr.abort()
                //     }, opts.timeout)
                // }
                return xhr
            }

            /***/
        },
        /* 8 */
        /***/ function (module, exports) {


            function JSONP(opts) {
                var callbackFunction = opts.jsonpCallbackFunction || generateCallbackFunction();
                var jsonpCallback = opts.jsonpCallback || 'callback'
                var xhr = document.createElement('script')
                if (xhr.charset) {
                    xhr.charset = opts.charset
                }
                xhr.onerror = xhr[useOnload ? 'onload' : 'onreadystatechange'] = function (e) {
                    var execute = /loaded|complete|undefined/i.test(xhr.readyState)
                    if (e && e.type === 'error') {
                        events['error'] && events['error']()
                    } else if (execute) {
                        setTimeout(function () {
                            xhr.abort()
                        }, 0)
                    }
                }

                var events = {}

                xhr.on = function (type, fn) {
                    events[type] = fn
                }

                xhr.abort = function () {
                    events = {}
                    removeNode(xhr)
                    clearFunction(callbackFunction)
                }
                xhr.open = function (a, url) {
                    window[callbackFunction] = function (response) {
                        events['load'] && events['load']({
                            status: 200,
                            statusText: 'ok',
                            response: response
                        })
                        clearFunction(callbackFunction)
                    }
                    var head = document.getElementsByTagName('head')[0]

                    url += (url.indexOf('?') === -1) ? '?' : '&';
                    xhr.setAttribute('src', url + jsonpCallback + '=' + callbackFunction);
                    head.insertBefore(xhr, head.firstChild)
                    if (typeof opts.timeout === 'number') {
                        setTimeout(function () {
                            events['timeout'] && events['timeout']()
                            xhr.abort()
                        }, opts.timeout)
                    }
                }
                return xhr
            }


            function generateCallbackFunction() {
                return ('jsonp' + Math.random()).replace(/0\./, '')
            }

            // Known issue: Will throw 'Uncaught ReferenceError: callback_*** is not defined' error if request timeout
            function clearFunction(functionName) {
                // IE8 throws an exception when you try to delete a property on window
                // http://stackoverflow.com/a/1824228/751089
                try {
                    delete window[functionName];
                } catch (e) {
                    window[functionName] = undefined;
                }
            }

            var f = document.createDocumentFragment()
            var useOnload = 'textContent' in document

            function removeNode(node) {
                f.appendChild(node)
                f.removeChild(node)
                node.onload = onerror = onreadystatechange = function () {
                }
                return node
            }

            module.exports = JSONP

            /***/
        },
        /* 9 */
        /***/ function (module, exports) {

            //https://msdn.microsoft.com/en-us/library/cc288060(v=VS.85).aspx
            module.exports = function XDR(opts) {
                var xhr = new XDomainRequest()
                'load,error,timeout'.replace(/\w+/g, function (method) {
                    xhr['on' + method] = function () {
                        if (events[method]) {
                            events[method](xhr)
                        }
                    }
                })
                var events = {}
                xhr.on = function (type, fn) {
                    events[type] = fn
                }
                xhr.onabort = function () {
                    events = {}
                }
                if (typeof opts.timeout === 'number') {
                    xhr.timeout = opts.timeout
                }
                return xhr
            }

            /***/
        },
        /* 10 */
        /***/ function (module, exports) {


            module.exports = function XHR(opts) {
                var xhr = new XMLHttpRequest
                'load,error,timeout'.replace(/\w+/g, function (method) {
                    xhr['on' + method] = function () {
                        if (events[method]) {
                            events[method](xhr)
                        }
                    }
                })
                var events = {}

                xhr.on = function (type, fn) {
                    events[type] = fn
                }

                xhr.onabort = function () {
                    events = {}
                }

                if (opts.credentials === 'include') {
                    xhr.withCredentials = true
                }

                if ('responseType' in xhr && ('Blob' in window)) {
                    var msie = document.documentMode || (window.XMLHttpRequest ? 7 : 6)
                    if (msie !== 10 && msie !== 11) {
                        xhr.responseType = 'blob'
                    }
                }

                return xhr
            }

            /***/
        }
        /******/])
});
;

 

聲明:在封裝的過程中,由於考慮到項目的實際情況我封裝的fetch可以在get中設置body,其本質是把body中的數據拼接到url上

 

在使用原生fetch的時候get,head請求是不能設置body的,否則會報錯

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM