知识 分享 互助 懒人建站

    懒人建站专注于网页素材下载,提供网站模板、网页设计、ps素材、图片素材等,服务于【个人站长】【网页设计师】和【web开发从业者】的代码素材与设计素材网站。

    懒人建站提供网页素材下载、网站模板
    知识 分享 互助!

    fetch的用法(fetch新一代ajax请求方案)

    作者:佳明妈 来源:web前端开发 2016-10-17 人气:
    fetch的用法,这篇fetch文章转载自大神的博客,原文已对fetch的用法阐述很明白,没必要在画蛇添足,原文地址:http://www.html5online.com.cn/articles/2015051301.html 来自www.html5online.com.cn的一篇f

    fetch的用法,这篇fetch文章转载自大神的博客,原文已对fetch的用法阐述很明白,没必要在画蛇添足,原文地址:http://www.html5online.com.cn/articles/2015051301.html

    来自www.html5online.com.cn的一篇fetch的用法

    基本的Fetch请求

    让我们首先来比较一个XMLHttpRequest使用示例与fetch方法的使用示例。该示例向服务器端发出请求,得到响应并使用JSON将其解析。

    XMLHttpRequest

    一个XMLHttpRequest需要设置两个事件回调函数,一个用于获取数据成功时调用,另一个用于获取数据失败时调用,以及一个open()方法调用及一个send()方法调用。

    function reqListener(){
        var data=JSON.parse(this.responseText);
        console.log(data);
    }
    function reqError(err){
        console.log("Fetch错误:"+err);
    }
    var oReq=new XMLHttpRequest();
    oReq.onload=reqListener;
    oReq.onerror=reqError;
    oReq.open("get","/students.json",true);
    oReq.send();

    Fetch

    一个fetch()方法的使用代码示例如下所示:

    fetch("/students.json")
    .then(
        function(response){
            if(response.status!==200){
                console.log("存在一个问题,状态码为:"+response.status);
                return;
            }
            //检查响应文本
            response.json().then(function(data){
                console.log(data);
            });
        }
    )
    .catch(function(err){
        console.log("Fetch错误:"+err);
    });

    在上面这个示例中,我们在使用JSON解析响应前首先检查响应状态码是否为200。

    一个fetch()请求的响应为一个Stream对象,这表示当我们调用json()方法,将返回一个Promise对象,因为流的读取将为一个异步过程。

    响应元数据

    在上一个示例中我们检查了Response对象的状态码,同时展示了如何使用JSON解析响应数据。我们可能想要访问响应头等元数据,代码如下所示:

    fetch("/students.json")
    .then(
        function(response){
            console.log(response.headers.get('Content-Type'));
            console.log(response.headers.get('Date'));
            console.log(response.status);
            console.log(response.statusText);
            console.log(response.type);
            console.log(response.url);
        }
    )

    响应类型

    当我们发出一个fetch请求时,响应类型将会为以下几种之一:“basic”、“cors”或“opaque”。这些类型标识资源来源,提示你应该怎样对待响应流。

    当请求的资源在相同域中时,响应类型为“basic”,不严格限定你如何处理这些资源。

    如果请求的资源在其他域中,将返回一个CORS响应头。响应类型为“cors”。“cors”响应限定了你只能在响应头中看见“Cache-Control”、“Content-Language”、“Content-Type”、“Expires”、“Last-Modified”以及“Progma”。

    一个“opaque”响应针对的是访问的资源位于不同域中,但没有返回CORS响应头的场合。如果响应类型为“opaque”,我们将不能查看数据,也不能查看响应状态,也就是说我们不能检查请求成功与否。目前为止不能在页面脚本中请求其他域中的资源。

    你可以为fetch请求定义一个模式以确保请求有效。可以定义的模式如下所示:

    • "same-origin":只在请求同域中资源时成功,其他请求将被拒绝。
    • "cors":允许请求同域及返回CORS响应头的域中的资源。
    • "cors-with-forced-preflight":在发出实际请求前执行preflight检查。
    • "no-cors"针对的是向其他不返回CORS响应头的域中的资源发出的请求(响应类型为“opaque”),但如前所述,目前在页面脚本代码中不起作用。

    为了定义模式,在fetch方法的第二个参数中添加选项对象并在该对象中定义模式:

    fetch("http://www.html5online.com.cn/cors-enabled/students.json",{mode:"cors"})
    .then(
        function(response){
            console.log(response.headers.get('Content-Type'));
            console.log(response.headers.get('Date'));
            console.log(response.status);
            console.log(response.statusText);
            console.log(response.type);
            console.log(response.url);
        }
    )
    .catch(function(err){
        console.log("Fetch错误:"+err);
    });

    Promise方法链

    Promise API的一个重大特性是可以链接方法。对于fetch来说,这允许你共享fetch请求逻辑。

    如果使用JSON API,你需要检查状态并且使用JSON对每个响应进行解析。你可以通过在不同的返回Promise对象的函数中定义状态及使用JSON进行解析来简化代码,你将只需要关注于处理数据及错误:

    function status(response){
        if(response.status>=200 && response.status<300){
            return Promise.resolve(response);
        }
        else{
            return Promise.reject(new Error(response.statusText));
        }
    }
    function json(response){
        return response.json();
    }
    fetch("/students.json")
    .then(status)
    .then(json)
    .then(function(data){
        console.log("请求成功,JSON解析后的响应数据为:",data);
    })
    .catch(function(err){
        console.log("Fetch错误:"+err);
    });

    在上述代码中,我们定义了status函数,该函数检查响应的状态码并返回Promise.resolve()方法或Promise.reject()方法的返回结果(分别为具有肯定结果的Promise及具有否定结果的Promise)。这是fetch()方法链中的第一个方法。如果返回肯定结果,我们调用json()函数,该函数返回来自于response.json()方法的Promise对象。在此之后我们得到了一个被解析过的JSON对象,如果解析失败Promise将返回否定结果,导致catch段代码被执行。

    这样书写的好处在于你可以共享fetch请求的逻辑,代码容易阅读、维护及测试。

    POST请求

    在Web应用程序中经常需要使用POST方法提交页面中的一些数据。

    为了执行POST提交,我们可以将method属性值设置为post,并且在body属性值中设置需要提交的数据。

    fetch(url,{
        method:"post",
        headers:{
            "Content-type":"application:/x-www-form-urlencoded:charset=UTF-8"
        },
        body:"name=lulingniu&age=40"
    })
    .then(status)
    .then(json)
    .then(function(data){
        console.log("请求成功,JSON解析后的响应数据为:",data);
    })
    .catch(function(err){
        console.log("Fetch错误:"+err);
    });

    使用Fetch请求发送凭证

    你可能想要使用Fetch发送带有诸如cookie之类的凭证的请求。你可以在选项对象中将credentials属性值设置为“include”:

    fetch(url,{
    credentials:"include"
    })

    来自segmentfault.com的一篇fetch用法介绍文章

    虽然有装逼的感觉,不过文章写的还是不错,还是应该感谢作者,原文地址:http://www.html5online.com.cn/articles/2015051301.html

    Fetch API 是基于 Promise 设计,有必要先学习一下 Promise,推荐阅读 MDN Promise 教程。旧浏览器不支持 Promise,需要使用 polyfill es6-promise 。

    本文不是 Fetch API 科普贴,其实是讲异步处理和 Promise 的。Fetch API 很简单,看文档很快就学会了。推荐 MDN Fetch 教程 和 万能的WHATWG Fetch 规范

    Why Fetch

    XMLHttpRequest 是一个设计粗糙的 API,不符合关注分离(Separation of Concerns)的原则,配置和调用方式非常混乱,而且基于事件的异步模型写起来也没有现代的 Promise,generator/yield,async/await 友好。

    Fetch 的出现就是为了解决 XHR 的问题,拿例子说明:

    使用 XHR 发送一个 json 请求一般是这样:

    var xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    xhr.responseType = 'json';
    
    xhr.onload = function() {
      console.log(xhr.response);
    };
    
    xhr.onerror = function() {
      console.log("Oops, error");
    };
    
    xhr.send();

    使用 Fetch 后,顿时看起来好一点

    fetch(url).then(function(response) {
      return response.json();
    }).then(function(data) {
      console.log(data);
    }).catch(function(e) {
      console.log("Oops, error");
    });

    使用 ES6 的 箭头函数 后:

    fetch(url).then(response => response.json())
      .then(data => console.log(data))
      .catch(e => console.log("Oops, error", e))

    现在看起来好很多了,但这种 Promise 的写法还是有 Callback 的影子,而且 promise 使用 catch 方法来进行错误处理的方式有点奇怪。不用急,下面使用 async/await 来做最终优化:

    注:async/await 是非常新的 API,属于 ES7,目前尚在 Stage 1(提议) 阶段,这是它的完整规范。使用 Babel 开启 runtime 模式后可以把 async/await 无痛编译成 ES5 代码。也可以直接使用 regenerator 来编译到 ES5。

    try {
      let response = await fetch(url);
      let data = response.json();
      console.log(data);
    } catch(e) {
      console.log("Oops, error", e);
    }
    // 注:这段代码如果想运行,外面需要包一个 async function

    duang~~ 的一声,使用 await 后,写异步代码就像写同步代码一样爽。await 后面可以跟 Promise 对象,表示等待 Promiseresolve() 才会继续向下执行,如果 Promise 被 reject() 或抛出异常则会被外面的 try...catch 捕获。

    Promise,generator/yield,await/async 都是现在和未来 JS 解决异步的标准做法,可以完美搭配使用。这也是使用标准 Promise 一大好处。最近也把项目中使用第三方 Promise 库的代码全部转成标准 Promise,为以后全面使用 async/await 做准备。

    另外,Fetch 也很适合做现在流行的同构应用,有人基于 Fetch 的语法,在 Node 端基于 http 库实现了 node-fetch,又有人封装了用于同构应用的 isomorphic-fetch

    注:同构(isomorphic/universal)就是使前后端运行同一套代码的意思,后端一般是指 NodeJS 环境。

    总结一下,Fetch 优点主要有:

    1. 语法简洁,更加语义化

    2. 基于标准 Promise 实现,支持 async/await

    3. 同构方便,使用 isomorphic-fetch

    Fetch 启用方法

    下面是重点↓↓↓

    先看一下 Fetch 原生支持率:
    fetch的用法

    原生支持率并不高,幸运的是,引入下面这些 polyfill 后可以完美支持 IE8+ :

    1. 由于 IE8 是 ES3,需要引入 ES5 的 polyfill: es5-shim, es5-sham

    2. 引入 Promise 的 polyfill: es6-promise

    3. 引入 fetch 探测库:fetch-detector

    4. 引入 fetch 的 polyfill: fetch-ie8

    5. 可选:如果你还使用了 jsonp,引入 fetch-jsonp

    6. 可选:开启 Babel 的 runtime 模式,现在就使用 async/await

    Fetch polyfill 的基本原理是探测是否存在 window.fetch 方法,如果没有则用 XHR 实现。这也是 github/fetch 的做法,但是有些浏览器(Chrome 45)原生支持 Fetch,但响应中有中文时会乱码,老外又不太关心这种问题,所以我自己才封装了 fetch-detector 和fetch-ie8 只在浏览器稳定支持 Fetch 情况下才使用原生 Fetch。这些库现在每天有几千万个请求都在使用,绝对靠谱!

    终于,引用了这一堆 polyfill 后,可以愉快地使用 Fetch 了。但要小心,下面有坑:

    Fetch 常见坑

    • Fetch 请求默认是不带 cookie 的,需要设置 fetch(url, {credentials: 'include'})

    • 服务器返回 400,500 错误码时并不会 reject,只有网络错误这些导致请求不能完成时,fetch 才会被 reject。

    竟然没有提到 IE,这实在太不科学了,现在来详细说下 IE

    IE 使用策略

    所有版本的 IE 均不支持原生 Fetch,fetch-ie8 会自动使用 XHR 做 polyfill。但在跨域时有个问题需要处理。

    IE8, 9 的 XHR 不支持 CORS 跨域,虽然提供 XDomainRequest,但这个东西就是玩具,不支持传 Cookie!如果接口需要权限验证,还是乖乖地使用 jsonp 吧,推荐使用 fetch-jsonp。如果有问题直接提 issue,我会第一时间解决。

    标准 Promise 的不足

    由于 Fetch 是典型的异步场景,所以大部分遇到的问题不是 Fetch 的,其实是 Promise 的。ES6 的 Promise 是基于 Promises/A+ 标准,为了保持简单简洁,只提供极简的几个 API。如果你用过一些牛 X 的异步库,如 jQuery(不要笑) 、Q.js 或者 RSVP.js,可能会感觉 Promise 功能太少了。

    没有 Deferred

    Deferred 可以在创建 Promise 时可以减少一层嵌套,还有就是跨方法使用时很方便。
    ECMAScript 11 年就有过 Deferred 提案,但后来没被接受。其实用 Promise 不到十行代码就能实现 Deferred:es6-deferred。现在有了 async/await,generator/yield 后,deferred 就没有使用价值了。

    没有获取状态方法:isRejected,isResolved

    标准 Promise 没有提供获取当前状态 rejected 或者 resolved 的方法。只允许外部传入成功或失败后的回调。我认为这其实是优点,这是一种声明式的接口,更简单。

    缺少其它一些方法:always,progress,finally

    always 可以通过在 then 和 catch 里重复调用方法实现。finally 也类似。progress 这种进度通知的功能还没有用过,暂不知道如何替代。

    Fetch 替换 XHR 只是时间问题,现在看到国外很多新的库都默认使用了 Fetch。

    最后再做一个大胆预测:由于 async/await 这类新异步语法的出现,第三方的 Promise 类库会逐渐被标准 Promise 替代,使用 polyfill 是现在比较明智的做法。
    原文地址:http://www.html5online.com.cn/articles/2015051301.html
    原文地址:http://www.html5online.com.cn/articles/2015051301.html

    ↓ 查看全文

    fetch的用法(fetch新一代ajax请求方案)由懒人建站收集整理,您可以自由传播,请主动带上本文链接

    懒人建站就是免费分享,觉得有用就多来支持一下,没有能帮到您,懒人也只能表示遗憾,希望有一天能帮到您。

    fetch的用法(fetch新一代ajax请求方案)-最新评论