可谓同源?URL由协议、域名、端口和路径组成,若是两个URL的协议、域名和端口相同,则表示他们同源。浏览器的同源策略,限制了来自不一样源 的"document"或脚本,对当前"document"读取或设置某些属性,即从一个域上加载的脚本不容许访问另一个域的文档属性。好比一个恶意网 站的页面经过iframe嵌入了银行的登陆页面(两者不一样源),若是没有同源限制,恶意网页上的javascript脚本就能够在用户登陆银行的时候获取 用户名和密码。所谓道高一尺魔高一丈,虽然浏览器以同源策略限制了咱们随意请求资源,可是从这个策略出现开始就有不少各类各样的Hacker技巧来。javascript
一、Jsonpphp
二、CORS:跨域资源共享html
三、postMessagejava
具体原理和用法请参照:http://www.javashuo.com/article/p-slymzbdg-h.htmljquery
Fetch API提供了一个fetch()
方法,它被定义在BOM的window
对象中,你能够用它来发起对远程资源的请求。 该方法返回的是一个ES6的Promise对象,让你可以对请求的返回结果进行检索。 它是 W3C 的正式标准 。git
Fetch API从提出到实现一直存在着争议,因为一直现存的历史缘由(例如HTML5的拖拽API被认为太过稀疏日常,Web Components标准被指意义不大)。 所以从新设计一个新的API来替代久经沙场历练的XMLHttpRequest
就变得阻力重重。es6
其中一种反对观点认为,Promises缺乏了一些重要的XMLHttpRequest
的使用场景。例如, 使用标准的ES6 Promise你没法收集进入信息或中断请求。而Fetch的狂热开发者更是试图提供Promise API的扩展用于取消一个Promise。 这个提议有点自挖墙角的意思,由于将这将让Promise变得不符合标准。但这个提议或许会致使将来出现一个可取消的Promise标准。 但另外一方面,使用XMLHttpRequest
你能够模拟进度(监听progress
事件),也能够取消请求(使用abort()
方法)。 可是,若是有必要你也可使用Promise来包裹它。github
另外一种反对观点认为,Web平台须要的是更多底层的API,而不是高层的API。对此的回答偏偏是, Fetch API足够底层,由于当前的WHATWG标准定义了XMLHttpRequest.send()
方法其实等同于fetch的Requset
对象。 Fetch中的Response.body
实现了getReader()
方法用于渐增的读取原始字节流。 例如,若是照片列表过大而放不进内存的话,你可使用下面的方法来处理:web
function streamingDemo() { var req = new Request(URL, {method: 'GET', cache: 'reload'}); fetch(req).then(function(response) { var reader = response.body.getReader(); return reader.read(); }).then(function(result, done) { if (!done) { // do something with each chunk } }); }
在上面的代码中处理器函数一块一块的接收响应体,而不是一次性的。当数据所有被读完后会将done
标记设置为true。 在这种方式下,每次你只须要处理一个chunk,而不是一次性的处理整个响应体。json
一、语法简洁,更加语义化
二、基于标准 Promise 实现,支持 async/await
三、同构方便,使用 isomorphic-fetch
因为 Fetch 是典型的异步场景,因此大部分遇到的问题不是 Fetch 的,实际上是 Promise 的。ES6 的 Promise 是基于 Promises/A+ 标准,为了保持 简单简洁 ,只提供极简的几个 API。若是你用过一些牛 X 的异步库,如 jQuery(不要笑) 、Q.js 或者 RSVP.js,可能会感受 Promise 功能太少了。
(1)没有 Deferred
Deferred 能够在建立 Promise 时能够减小一层嵌套,还有就是跨方法使用时很方便。
ECMAScript 11 年就有过 Deferred 提案,但后来没被接受。其实用 Promise 不到十行代码就能实现 Deferred:es6-deferred。如今有了 async/await,generator/yield 后,deferred 就没有使用价值了。
(2)没有获取状态方法:isRejected,isResolved
标准 Promise 没有提供获取当前状态 rejected 或者 resolved 的方法。只容许外部传入成功或失败后的回调。我认为这实际上是优势,这是一种声明式的接口,更简单。
(3)缺乏其它一些方法:always,progress,finally
always 能够经过在 then 和 catch 里重复调用方法实现。finally 也相似。progress 这种进度通知的功能尚未用过,暂不知道如何替代。
(4)不能中断,没有 abort、terminate、onTimeout 或 cancel 方法
Fetch 和 Promise 同样,一旦发起,不能中断,也不会超时,只能等待被 resolve 或 reject。幸运的是,whatwg 目前正在尝试解决这个问题 whatwg/fetch#27
(1)get请求
fetch("/data.json").then(function(res) { // res instanceof Response == true. if (res.ok) { res.json().then(function(data) { console.log(data.entries); }); } else { console.log("Looks like the response wasn't perfect, got status", res.status); } }, function(e) { console.log("Fetch failed!", e); }); fetch('http://nero-zou.com/test.json') .then((response) => { if (response.ok) { return response.json() } else { console.error('服务器繁忙,请稍后再试;\r\nCode:' + response.status) } }) .then((data) => { console.log(data) }) .catch((err)=> { console.error(err) })
(2)post请求
fetch('/users', { method: 'post', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Hubot', login: 'hubot', }) }) fetch("http://www.example.org/submit.php", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: "firstName=Nikhil&favColor=blue&password=easytoguess" }).then(function(res) { if (res.ok) { alert("Perfect! Your settings are saved."); } else if (res.status == 401) { alert("Oops! You are not authorized."); } }, function(e) { alert("Error submitting form!"); });
(3)上传文件
var input = document.querySelector('input[type="file"]') var data = new FormData() data.append('file', input.files[0]) data.append('user', 'hubot') fetch('/avatars', { method: 'post', body: data })
Fetch 引入了 3 个接口,分别是 Headers
,Request
和 Response
。他们直接对应于的 HTTP 中相应的概念,可是基于隐私和安全考虑,也有些区别,例如支持 CORS 规则以及保证 cookies 不能被第三方获取。
自定义请求头信息极大地加强了请求的灵活性。咱们能够经过 new Headers()
来建立请求头:
Create an empty Headers instance var headers = new Headers(); // Add a few headers headers.append('Content-Type', 'text/plain'); headers.append('X-My-Custom-Header', 'CustomValue'); // Check, get, and set header values headers.has('Content-Type'); // true headers.get('Content-Type'); // "text/plain" headers.set('Content-Type', 'application/json'); // Delete a header headers.delete('X-My-Custom-Header'); // Add initial values var headers = new Headers({ 'Content-Type': 'text/plain', 'X-My-Custom-Header': 'CustomValue' });
一、Request对象表明了一次fetch
请求中的请求体部分,你能够自定义Request
对象:
method
- 使用的HTTP动词,GET
, POST
, PUT
, DELETE
, HEAD
url
- 请求地址,URL of the request
headers
- 关联的Header对象
referrer
- referrer
mode
- 请求的模式,主要用于跨域设置,cors
, no-cors
, same-origin
credentials
- 是否发送Cookie omit
, same-origin
redirect
- 收到重定向请求以后的操做,follow
, error
, manual
integrity
- 完整性校验
cache
- 缓存模式(default
, reload
, no-cache
)
二、使用方式以下
var request = new Request('/users.json', { method: 'POST', mode: 'cors', redirect: 'follow', headers: new Headers({ 'Content-Type': 'text/plain' }) }); // Now use it! fetch(request).then(function() { /* handle response */ });
三、Request对象中mode属性详细介绍
(1)same-origin
该模式很简单,若是一个请求是跨域的,那么将返回一个 error
,这样确保全部的请求遵照同源策略。
var arbitraryUrl = document.getElementById("url-input").value; fetch(arbitraryUrl, { mode: "same-origin" }).then(function(res) { console.log("Response succeeded?", res.ok); }, function(e) { console.log("Please enter a same-origin URL!"); });
(2)no-cors
该模式容许来自 CDN 的脚本、其余域的图片和其余一些跨域资源,可是首先有个前提条件,就是请求的 method 只能是HEAD
、GET
或 POST
。此外,若是 ServiceWorkers 拦截了这些请求,它不能随意添加或者修改除这些以外 Header 属性。第三,JS 不能访问 Response 对象中的任何属性,这确保了跨域时 ServiceWorkers 的安全和隐私信息泄漏问题。
(3)cors
该模式一般用于跨域请求,用来从第三方提供的 API 获取数据。该模式遵照 CORS 协议,并只有有限的一些 Header 被暴露给 Response 对象,可是 body 是可读的。例如,获取一个 Flickr 最感兴趣的照片的清单:
var u = new URLSearchParams(); u.append('method', 'flickr.interestingness.getList'); u.append('api_key', '<insert api key here>'); u.append('format', 'json'); u.append('nojsoncallback', '1'); var apiCall = fetch('https://api.flickr.com/services/rest?' + u); apiCall.then(function(response) { return response.json().then(function(json) { // photo is a list of photos. return json.photos.photo; }); }).then(function(photos) { photos.forEach(function(photo) { console.log(photo.title); }); });
你将没法从 Headers 中读取 Date
属性,由于 Flickr 在 Access-Control-Expose-Headers
中设置了不容许读取它。
response.headers.get("Date"); // null
另外,credentials
属性决定了是否能够跨域访问 cookie 。该属性与 XHR 的
withCredentials
标志相同,可是只有三个值,分别是 omit
(默认)、same-origin
和 include
。
Request 对象也提供了客户端缓存机制(caching hints)。这个属性还在安全复审阶段。Firefox 提供了这个属性,但目前还不起做用。
fetch
返回的 then
方法有一个 response
参数,它是一个 Response
实例。
Response
有以下属性:
Response
有以下方法:
clone() - 复制一份response
error() - 返回一个与网络相关的错误
redirect() - 返回了一个能够重定向至某URL的response.
arrayBuffer() - 返回一个带有ArrayBuffer的Promise.
blob() - 返回一个带有Blob的Promise.
formData() - 返回一个带有FormData的Promise.
json() - 返回一个带有JSON格式对象的Promise.
text() - 返回一个带有文本的Promise.
原生支持率并不高,幸运的是,引入下面这些 polyfill 后能够完美支持 IE8+ :
能够经过检查 Headers
、Request
、Response
或 fetch
在 window 或 worker 做用域中是否存在,来检查是否支持 Fetch API。
Fetch polyfill 的基本原理是探测是否存在 window.fetch
方法,若是没有则用 XHR 实现。这也是 github/fetch 的作法,可是有些浏览器(Chrome 45)原生支持 Fetch,但响应中有中文时会乱码,老外又不太关心这种问题,因此封装了 fetch-detector
和 fetch-ie8
只在浏览器稳定支持 Fetch 状况下才使用原生 Fetch。这些库如今 天天有几千万个请求都在使用,绝对靠谱 !
用到了isomorphic-fetch这个库
// 自动进行全局的ES6 Promise的Polyfill require('es6-promise').polyfill(); require('isomorphic-fetch');
http://www.csdn.net/article/1970-01-01/2826065
https://github.com/camsong/blog/issues/2
http://www.tuicool.com/articles/M7NRr27 看
http://bubkoo.com/2015/05/08/introduction-to-fetch/ 看
https://segmentfault.com/a/1190000006095018#articleHeader14 看
一、本博客中的文章摘自网上的众多博客,仅做为本身知识的补充和整理,并分享给其余须要的coder,不会用于商用。
二、由于不少博客的地址看完没有及时作保存,因此不少不会在这里标明出处,很是感谢各位大牛的分享,也但愿你们理解。