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


Posted in Javascript onJune 14, 2016

XMLHttpRequest来完成ajax有些老而过时了。

fetch()能让我们完成类似 XMLHttpRequest (XHR) 提供的ajax功能。它们之间的主要区别是,Fetch API 使用了 Promises,它让接口更简单、简洁,避免了回调的复杂性,省去了使用复杂的 XMLHttpRequest API。

如果你之前未使用过Promises,你应该先看看《JavaScript Promises 用法》这篇文章。

一、基本Fetch用法

让我们先用一个例子来比较一下使用 XMLHttpRequest 和使用 fetch 之间的不同。我们要请求一个URL,获取JSON格式的返回结果。

XMLHttpRequest
一个 XMLHttpRequest 请求需要两个监听器来捕捉 success 和 error 两种情形,而且需要调用 open() 和 send() 方法。

function reqListener() { 
 var data = JSON.parse(this.responseText); 
 console.log(data); 
}

function reqError(err) { 
 console.log('Fetch Error :-S', err); 
}

var oReq = new XMLHttpRequest(); 
oReq.onload = reqListener; 
oReq.onerror = reqError; 
oReq.open('get', './api/some.json', true); 
oReq.send();

Fetch
我们的 fetch 请求的代码基本上是这样的:

fetch('./api/some.json') 
 .then( 
 function(response) { 
  if (response.status !== 200) { 
  console.log('Looks like there was a problem. Status Code: ' + 
   response.status); 
  return; 
  }

  // Examine the text in the response 
  response.json().then(function(data) { 
  console.log(data); 
  }); 
 } 
 ) 
 .catch(function(err) { 
 console.log('Fetch Error :-S', err); 
 });

我们首先检查请求响应的状态是否是 200,然后才按照 JSON 对象分析响应数据。

fetch()请求获取的内容是一个 Stream 对象。也就是说,当我们调用 json() 方法时,返回的仍是一个 Promise 对象,这是因为对 stream 的读取也是异步的。

返回数据对象的元数据(Metadata)

在上面的例子中,我看到了服务器响应对象Response的基本状态,以及如何转换成JSON。返回的相应对象Response里还有很多的元数据信息,下面是一些:

fetch('users.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); 
});

响应的对象Response类型

当我们执行一个fetch请求时,响应的数据的类型response.type可以是“basic”, “cors” 或 “opaque”。这些类型用来说明应该如何对待这些数据和数据的来源。

当请求发起自同一个域时,响应的类型将会是“basic”,这时,对响应内容的使用将没有任何限制。

如果请求来自另外某个域,而且响应的具有CORs头信息,那么,响应的类型将是“cors”。 “cors” 和 “basic” 类型的响应基本是一样的,区别在于,“cors”类型的响应限制你只能看到的头信息包括`Cache-Control`, `Content-Language`, `Content-Type`, `Expires`, `Last-Modified`, 和 `Pragma`。

“opaque”类型的响应说明请求来自另外一个域,并且不具有 CORS 头信息。一个opaque类型的响应将无法被读取,而且不能读取到请求的状态,无法看到请求的成功与否。当前的 fetch() 实现无法执行这样的请求。

你可以给fetch请求指定一个模式,要求它只执行规定模式的请求。这个模式可以分为:

“same-origin” 只有来自同域的请求才能成功,其它的均将被拒绝。
“cors” 允许不同域的请求,但要求有正确的 CORs 头信息。
“cors-with-forced-preflight” 在执行真正的调用前先执行preflight check。
“no-cors” 目前这种模式是无法执行的。
定义模式的方法是,使用一个参数对象当做fetch方法的第二个参数:

fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'}) 
 .then(function(response) { 
 return response.text(); 
 }) 
 .then(function(text) { 
 console.log('Request successful', text); 
 }) 
 .catch(function(error) { 
 log('Request failed', error) 
 });

串联 Promises

Promises最大的一个特征是,你可以串联各种操作。对于fetch来说,我们可以在各个fetch操作里共享一些逻辑操作。

在使用JSON API时,我们需要检查每次请求响应的状态,然后解析成JSON对象。使用promise,我们可以简单的将分析状态和解析JSON的代码放到一个单独函数里,然后当做promise返回,这样就是代码更条理了。

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('users.json') 
 .then(status) 
 .then(json) 
 .then(function(data) { 
 console.log('Request succeeded with JSON response', data); 
 }).catch(function(error) { 
 console.log('Request failed', error); 
 });

我们用 status 函数来检查 response.status 并返回 Promise.resolve() 或 Promise.reject() 的结果,这个结果也是一个 Promise。我们的fetch() 调用链条中,首先如果fetch()执行结果是 resolve,那么,接着会调用 json() 方法,这个方法返回的也是一个 Promise,这样我们就得到一个分析后的JSON对象。如果分析失败,将会执行reject函数和catch语句。

你会发现,在fetch请求中,我们可以共享一些业务逻辑,使得代码易于维护,可读性、可测试性更高。

用fetch执行表单数据提交

在WEB应用中,提交表单是非常常见的操作,用fetch来提交表单数据也是非常简洁。

fetch里提供了 method 和 body 参数选项。

fetch(url, { 
 method: 'post', 
 headers: { 
  "Content-type": "application/x-www-form-urlencoded; charset=UTF-8" 
 }, 
 body: 'foo=bar&lorem=ipsum' 
 })
 .then(json) 
 .then(function (data) { 
 console.log('Request succeeded with JSON response', data); 
 }) 
 .catch(function (error) { 
 console.log('Request failed', error); 
 });

在Fetch请求里发送用户身份凭证信息

如果你想在fetch请求里附带cookies之类的凭证信息,可以将 credentials 参数设置成 “include” 值。

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

显而易见,fetch API相比起传统的 XMLHttpRequest (XHR) 要简单的多,相比起jQuery里提供ajax API也丝毫不逊色。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery源码分析-05异步队列 Deferred 使用介绍
Nov 14 Javascript
extjs render 用法介绍
Sep 11 Javascript
将form表单中的元素转换成对象的方法适用表单提交
May 02 Javascript
JavaScript中常见的字符串操作函数及用法汇总
May 04 Javascript
jQuery网页版打砖块小游戏源码分享
Aug 20 Javascript
AngularJS入门教程之REST和定制服务详解
Aug 19 Javascript
vue 2.0组件与v-model详解
Mar 27 Javascript
Javascript网页抢红包外挂实现分享
Jan 11 Javascript
Vue 中使用vue2-highcharts实现top功能的示例
Mar 05 Javascript
JavaScript防止全局变量污染的方法总结
Aug 02 Javascript
vue中多个倒计时实现代码实例
Mar 27 Javascript
Element Dialog对话框的使用示例
Jul 26 Javascript
深入理解jQuery 事件处理
Jun 14 #Javascript
使用jquery获取url及url参数的简单实例
Jun 14 #Javascript
JS操作JSON方法总结(推荐)
Jun 14 #Javascript
JavaScript Promise 用法
Jun 14 #Javascript
Javascript基础_简单比较undefined和null 值
Jun 14 #Javascript
Javascript缓存API
Jun 14 #Javascript
JS修改地址栏参数实例代码
Jun 14 #Javascript
You might like
星际争霸教主Flash的ID由来:你永远不会知道他之前的ID是www!
2019/01/18 星际争霸
ionCube 一款类似zend的PHP加密/解密工具
2010/07/25 PHP
(PHP实现)只使用++运算实现加法,减法,乘法,除法
2013/06/27 PHP
javascript实现链接单选效果的方法
2015/05/13 Javascript
JS模拟Dialog弹出浮动框效果代码
2015/10/16 Javascript
深入解析JavaScript中的数字对象与字符串对象
2015/10/21 Javascript
极力推荐10个短小实用的JavaScript代码段
2016/08/03 Javascript
浅谈DOM的操作以及性能优化问题-重绘重排
2017/01/08 Javascript
js canvas实现简单的图像扩散效果
2020/06/28 Javascript
Node.js中环境变量process.env的一些事详解
2017/10/26 Javascript
vue嵌套路由与404重定向实现方法分析
2018/05/04 Javascript
webpack4 处理SCSS的方法示例
2018/09/03 Javascript
Angular+Ionic使用queryParams实现跳转页传值的方法
2020/09/05 Javascript
[01:00:30]TFT vs VGJ.T Supermajor 败者组 BO3 第一场 6.5
2018/06/06 DOTA
[55:56]NB vs Infamous 2019国际邀请赛淘汰赛 败者组 BO3 第二场 8.22
2019/09/05 DOTA
利用django如何解析用户上传的excel文件
2017/07/24 Python
K-means聚类算法介绍与利用python实现的代码示例
2017/11/13 Python
一篇文章读懂Python赋值与拷贝
2018/04/19 Python
Python实现爬虫爬取NBA数据功能示例
2018/05/28 Python
Python使用字典的嵌套功能详解
2019/02/27 Python
python输入多行字符串的方法总结
2019/07/02 Python
python3的url编码和解码,自定义gbk、utf-8的例子
2019/08/22 Python
python 怎样将dataframe中的字符串日期转化为日期的方法
2019/09/26 Python
Python包,__init__.py功能与用法分析
2020/01/07 Python
如何把python项目部署到linux服务器
2020/08/26 Python
HTML5 与 XHTML2
2008/10/17 HTML / CSS
松本清官方海外旗舰店:日本最大的药妆连锁店
2017/11/21 全球购物
请写出char *p与"零值"比较的if语句
2014/09/24 面试题
Delphi CS笔试题
2014/01/04 面试题
《孔子拜师》教学反思
2014/02/24 职场文书
师德师风建设方案
2014/05/08 职场文书
鼓舞士气的口号
2014/06/16 职场文书
2014领导班子四风剖析对照检查材料思想汇报
2014/09/20 职场文书
优秀党务工作者先进事迹材料
2014/12/25 职场文书
硕士学位论文评语
2014/12/31 职场文书
php中配置文件保存修改操作 如config.php文件的读取修改等操作
2021/05/12 PHP