Fetch的使用及兼容ie的处理

本文介绍了Fetch API的使用及其在现代浏览器中的优势,如更好的可读性和可维护性。同时,针对IE浏览器的兼容性问题,文章讨论了Fetch在IE中的不支持情况,并提出了一种封装Fetch以兼容低版本IE的策略,包括使用XMLHttpRequest、XDomainRequest和ActiveXObject。通过这种方式,可以在保持使用Fetch的便利性的同时,解决IE浏览器的兼容性挑战。
摘要由CSDN通过智能技术生成

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) {
         
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值