AJAX半遮半掩的底层API是饱受诟病的一件事情. XMLHttpRequest 并不是专为Ajax而设计的. 虽然各种框架对 XHR 的封装已经足够好用, 但我们可以做得更好。更好用的API是 fetch 。下面简单介绍 window.fetch 方法, 在最新版的 Firefox 和 Chrome 中已经提供支持。

XMLHttpRequest

在我看来 XHR 有点复杂, 我不想解释为什么“XML”是大写,而“Http”是“骆峰式”写法。使用XHR的方式大致如下:

// 获取 XHR 非常混乱!
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
request = new ActiveXObject('Msxml2.XMLHTTP');
}
catch (e) {
try {
request = new ActiveXObject('Microsoft.XMLHTTP');
}
catch (e) {}
}
} // 打开连接, 发送数据.
request.open('GET', 'https://davidwalsh.name/ajax-endpoint', true);
request.send(null);

我们可以看出, XHR 其实是很杂乱的; 当然, 通过 JavaScript 框架可以很方便地使用XHR。

fetch 的基本使用

fetch 是全局量 window 的一个方法, 第一个参数是URL:

// url (必须), options (可选)
fetch('/some/url', {
method: 'get'
}).then(function(response) { }).catch(function(err) {
// 出错了;等价于 then 的第二个参数,但这样更好用更直观 :(
});

Battery API 类似, fetch API 也使用了 JavaScript Promises 来处理结果/回调:

// 对响应的简单处理
fetch('/some/url').then(function(response) { }).catch(function(err) {
// 出错了;等价于 then 的第二个参数,但这样更直观 :(
}); // 链式处理,将异步变为类似单线程的写法: 高级用法.
fetch('/some/url').then(function(response) {
return //... 执行成功, 第1步...
}).then(function(returnedValue) {
// ... 执行成功, 第2步...
}).catch(function(err) {
// 中途任何地方出错...在此处理 :(
});

如果你还不习惯 then 方式的写法,那最好学习一下,因为很快就会全面流行。

请求头(Request Headers)

自定义请求头信息极大地增强了请求的灵活性。我们可以通过 new Headers() 来创建请求头:

// 创建一个空的 Headers 对象,注意是Headers,不是Header
var headers = new Headers(); // 添加(append)请求头信息
headers.append('Content-Type', 'text/plain');
headers.append('X-My-Custom-Header', 'CustomValue'); // 判断(has), 获取(get), 以及修改(set)请求头的值
headers.has('Content-Type'); // true
headers.get('Content-Type'); // "text/plain"
headers.set('Content-Type', 'application/json'); // 删除某条请求头信息(a header)
headers.delete('X-My-Custom-Header'); // 创建对象时设置初始化信息
var headers = new Headers({
'Content-Type': 'text/plain',
'X-My-Custom-Header': 'CustomValue'
});

可以使用的方法包括: append, has, get, set, 以及 delete 。需要创建一个 Request 对象来包装请求头:

var request = new Request('/some-url', {
headers: new Headers({
'Content-Type': 'text/plain'
})
}); fetch(request).then(function() { /* handle response */ });

下面介绍 ResponseRequest 的使用方法!

Request 简介

Request 对象表示一次 fetch 调用的请求信息。传入 Request 参数来调用 fetch, 可以执行很多自定义请求的高级用法:

  • method - 支持 GET, POST, PUT, DELETE, HEAD
  • url - 请求的 URL
  • headers - 对应的 Headers 对象
  • referrer - 请求的 referrer 信息
  • mode - 可以设置 cors, no-cors, same-origin
  • credentials - 设置 cookies 是否随请求一起发送。可以设置: omit, same-origin
  • redirect - follow, error, manual
  • integrity - subresource 完整性值(integrity value)
  • cache - 设置 cache 模式 (default, reload, no-cache)

Request 的示例如下:

var request = new Request('/users.json', {
method: 'POST',
mode: 'cors',
redirect: 'follow',
headers: new Headers({
'Content-Type': 'text/plain'
})
}); // 使用!
fetch(request).then(function() { /* handle response */ });

只有第一个参数 URL 是必需的。在 Request 对象创建完成之后, 所有的属性都变为只读属性. 请注意, Request 有一个很重要的 clone 方法, 特别是在 Service Worker API 中使用时 —— 一个 Request 就代表一串流(stream), 如果想要传递给另一个 fetch 方法,则需要进行克隆。

fetch 的方法签名(signature,可理解为配置参数), 和 Request 很像, 示例如下:

fetch('/users.json', {
method: 'POST',
mode: 'cors',
redirect: 'follow',
headers: new Headers({
'Content-Type': 'text/plain'
})
}).then(function() { /* handle response */ });

因为 Request 和 fetch 的签名一致, 所以在 Service Workers 中, 你可能会更喜欢使用 Request 对象。关于 ServiceWorker 的相关博客请等待后续更新!

Response 简介

Response 代表响应, fetchthen 方法接收一个 Response 实例, 当然你也可以手动创建 Response 对象 —— 比如在 service workers 中可能会用到. Response 可以配置的参数包括:

  • type - 类型,支持: basic, cors
  • url
  • useFinalURL - Boolean 值, 代表 url 是否是最终 URL
  • status - 状态码 (例如: 200, 404, 等等)
  • ok - Boolean值,代表成功响应(status 值在 200-299 之间)
  • statusText - 状态值(例如: OK)
  • headers - 与响应相关联的 Headers 对象.
// 在 service worker 测试中手动创建 response
// new Response(BODY, OPTIONS)
var response = new Response('.....', {
ok: false,
status: 404,
url: '/'
}); // fetch 的 `then` 会传入一个 Response 对象
fetch('/')
.then(function(responseObj) {
console.log('status: ', responseObj.status);
});

Response 提供的方法如下:

  • clone() - 创建一个新的 Response 克隆对象.
  • error() - 返回一个新的,与网络错误相关的 Response 对象.
  • redirect() - 重定向,使用新的 URL 创建新的 response 对象..
  • arrayBuffer() - Returns a promise that resolves with an ArrayBuffer.
  • blob() - 返回一个 promise, resolves 是一个 Blob.
  • formData() - 返回一个 promise, resolves 是一个 FormData 对象.
  • json() - 返回一个 promise, resolves 是一个 JSON 对象.
  • text() - 返回一个 promise, resolves 是一个 USVString (text).

处理 JSON响应

假设需要请求 JSON —— 回调结果对象 response 中有一个json()方法,用来将原始数据转换成 javascript 对象:

fetch('https://davidwalsh.name/demo/arsenal.json').then(function(response) {
// 转换为 JSON
return response.json();
}).then(function(j) {
// 现在, `j` 是一个 JavaScript object
console.log(j);
});

当然这很简单 , 只是封装了 JSON.parse(jsonString) 而已, 但 json 方法还是很方便的。

处理基本的Text / HTML响应

JSON 并不总是理想的请求/响应数据格式, 那么我们看看如何处理 HTML或文本结果:

fetch('/next/page')
.then(function(response) {
return response.text();
}).then(function(text) {
// <!DOCTYPE ....
console.log(text);
});

如上面的代码所示, 可以在 Promise 链式的 then 方法中, 先返回 text() 结果 ,再获取 text 。

处理Blob结果

如果你想通过 fetch 加载图像或者其他二进制数据, 则会略有不同:

fetch('flowers.jpg')
.then(function(response) {
return response.blob();
})
.then(function(imageBlob) {
document.querySelector('img').src = URL.createObjectURL(imageBlob);
});

响应 Body mixin 的 blob() 方法处理响应流(Response stream), 并且将其读完。

提交表单数据(Posting Form Data)

另一种常用的 AJAX 调用是提交表单数据 —— 示例代码如下:

fetch('/submit', {
method: 'post',
body: new FormData(document.getElementById('comment-form'))
});

提交 JSON 的示例如下:

fetch('/submit-json', {
method: 'post',
body: JSON.stringify({
email: document.getElementById('email').value
answer: document.getElementById('answer').value
})
});

非常非常简单, 妈妈再也不用担心我的Ajax!

未完的故事(Unwritten Story)

fetch 是个很实用的API , 当前还不允许取消请求, 这使得很多程序员暂时不会考虑它。

新的 fetch API 比起 XHR 更简单也更智能。毕竟,它就是专为AJAX而设计的, 具有后发优势. 而我已经迫不及待地使用了, 即使现在兼容性还不是那么好!

本文简单介绍了 fetch 。更多信息请访问 Fetch简介。如果你要使用 fetch, 也想寻找 polyfill(兼容代码), 请点击: GitHub上的fetch实现 https://github.com/github/fetch

 
相关链接
https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
 

新一代AJAX API:FETCH的更多相关文章

  1. 新一代Ajax API --fetch

    之前 师傅跟我提过 一个新的Ajax API  fetch 今天看到一篇关于fetch的文章,受益匪浅. XMLHttpRequest并不是专为Ajax而设计的,虽然各种框架对XHR的封装已经足够好用 ...

  2. web API简介(一):API,Ajax和Fetch

    概述 今天逛MDN,无意中看到了web API简介,觉得挺有意思的,就认真读了一下. 下面是我在读的时候对感兴趣的东西的总结,供自己开发时参考,相信对其他人也有用. 什么是API API (Appli ...

  3. vue-d2admin-axios异步请求登录,先对比一下Jquery ajax, Axios, Fetch区别

    先说一下对比吧 Jquery ajax, Axios, Fetch区别之我见 引言 前端技术真是一个发展飞快的领域,我三年前入职的时候只有原生XHR和Jquery ajax,我们还曾被JQuery 1 ...

  4. 你不需要jQuery(三):新AJAX方法fetch()

    XMLHttpRequest来完成ajax有些老而过时了. fetch()能让我们完成类似 XMLHttpRequest (XHR) 提供的ajax功能.它们之间的主要区别是,Fetch API 使用 ...

  5. 理解 ajax、fetch和axios

    背景 ajax fetch.axios 优缺点 ajax基于jquery,引入时需要引入庞大的jquery库,不符合当下前端框架,于是fetch替代了ajax 由于fetch是比较底层,需要我们再次封 ...

  6. 前后端数据交互(六)——ajax 、fetch 和 axios 优缺点及比较

    一.ajax.fetch 和 axios 简介 1.1.ajax ajax是最早出现发送后端请求的技术,属于原生 js .ajax使用源码,请点击<原生 ajax 请求详解>查看.一般使用 ...

  7. Jquery ajax, Axios, Fetch区别

    1.   Jquery ajax, Axios, Fetch区别之我见 2.   ajax.axios.fetch之间的详细区别以及优缺点

  8. Jquery ajax, Axios, Fetch区别之我见(转载)

    来源:https://segmentfault.com/a/1190000012836882 引言 前端技术真是一个发展飞快的领域,我三年前入职的时候只有原生XHR和Jquery ajax,我们还曾被 ...

  9. 用ajax与fetch调用阿里云免费接口

    最近学习态度比较积极,打算用react做一个小个人应用网站...所以从阿里云上买了些免费的接口,什么QQ音乐排行查询接口.IP地址查询.天气预报等等.调用时,发现身份校验可以通过简单修改头部信息的方式 ...

随机推荐

  1. linux监控平台搭建-内存

    linux监控平台搭建-内存 上一篇文章说的硬盘.就写一下.更加重要的东西.在手机上面是RAM.机器是memory.内存是按照字节编址.每个地址的存储单元可以存放8bit的数据.cpu 通过内存地址获 ...

  2. spring mvc处理静态文件

    现在流行REST开发风格,REST风格的URL 是不希望看到例如:*.do后缀的. <servlet-mapping> <servlet-name>cxy</servle ...

  3. 洛谷 P 1387 最大正方形

    题目描述 在一个n*m的只包含0和1的矩阵里找出一个不包含0的最大正方形,输出边长. 输入输出格式 输入格式: 输入文件第一行为两个整数n,m(1<=n,m<=100),接下来n行,每行m ...

  4. 如何用DW设计界面 结合 VS设计后台代码

    原文发布时间为:2008-11-02 -- 来源于本人的百度文章 [由搬家工具导入] 问:在vs.net里有form标记,而dw里却没有,两个里面的标记代码都不一样,怎么能通用? 在.net里修改dw ...

  5. Android之观察者/被观察者模式Observer/Observable

    Android 本身也是有观察者模式的.虽然项目中很多需要通知数据改变的地方,用了EventBus,但是不得不说这个观察者模式还是很好用的.最近在开发新版本的时候引用了腾讯的IM,之前写直播的时候就用 ...

  6. react css module

    <div className={style['content-warp']}></div> <div className={style.search}></d ...

  7. mybatis 源码学习(二)sqlsession

    mybatis 中的sqlsession是一个非常重要的类.上篇我们分析了sessionfactory初始化配置文件,我们继续分析sessionfactory拿到会话进行的操作. 看这里.getMap ...

  8. Java 对象的序列化、反序列化

    对象的序列化(Serialize):将内存中的Java对象转换为与平台无关的二进制流(字节序列),然后存储在磁盘文件中,或通过网络传输给另一个网络节点. 对象的反序列化(Deserialize):获取 ...

  9. Android中的动画总结

    文章主要内容来源<Android开发艺术探索>,部分内容来源网上的文章,文中会有链接. Android系统提供了两个动画框架:属性动画框架和View动画框架. 两个动画框架都是可行的选项, ...

  10. TSimpleMsgPack的样例代码

    TSimpleMsgPack的样例代码 unit uMain; interface uses SimpleMsgPack, Windows, Messages, SysUtils, Variants, ...