美文网首页跨域
谷歌浏览器获取本地json文件跨域问题及JSONP的应用

谷歌浏览器获取本地json文件跨域问题及JSONP的应用

作者: celineWong7 | 来源:发表于2020-04-23 14:28 被阅读0次

最近需要读取本地json文件,找到了原生js方式和ajax方式,都会报跨域的问题。于是研究了下什么是跨域,为什么会跨域,以及JSONP解决方案的运用。

一、我是怎么遇到跨域问题的?

因为要读取本地json文件(test.json),分别使用了原生js方式和ajax方式(代码如下)。

// 原生方式  -   google会报跨域
window.onload = function () {
    var url = "./test.json";
    var request = new XMLHttpRequest();
    request.open("get", url); // 设置请求方法与路径
    request.send(null);// 读取本地,就不发送数据到服务器
    request.onload = function () { // XHR对象获取到返回信息后执行
        if (request.status == 200) { // 返回状态为200,即为数据获取成功
            var json = JSON.parse(request.responseText);
            console.log(json);
        }
    }
}
    // ajax请求json文件  -   google会报跨域
    // 要引入jq库文件
    $.ajax({
        url: "./test.json",// json文件位置
        type: "GET",
        dataType: "json",
        success: function(data) {
           console.log(name);
        }
    })

用谷歌浏览器和IE浏览器打开,都获取不到json数据,控制台报错:


谷歌浏览器访问本地文件的跨域报错提示

二、什么是跨域?

1. 首先,什么是域?

协议、域名、端口这三者相同,视为同一个域。
所以,只要协议,域名,端口有一个不同,就是跨域。

2. 为什么浏览器会报跨域的错?

这是因为浏览器有一个安全机制,叫做 同源策略(CROS),不同域的客户端脚本在无明确授权的情况下,是不能读取对方资源的。它保证了一个域的脚本只能读写本域内的资源,而无法访问其他域的资源。
所以,可以说跨域就是不同源。

但需要注意,并不是所有浏览器都用同源策略,比如火狐浏览器,就允许跨域。而且,即使是谷歌浏览器,也可以通过浏览器设置项改成允许跨域。

3. 本地html页面读取本地json文件是跨域?

按照上面我们分析的跨域场景是:协议,域名,端口有一个不同。
但看起来本地页面html的地址,和本地json文件的地址是在同一个域的感觉:

file:///Z:/celine/test/jsonp/demo.html
file:///Z:/celine/test/jsonp/test.json

而实际上,让我们仔细看看谷歌浏览器的报错内容,就可以发现,跨源请求仅支持协议方案。 :http, data, chrome, chrome-extension, https.,不支持file协议。
(谷歌报错内容:Access to XMLHttpRequest at 'file:///Z:/celine/test/jsonp/test.json' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

三、怎么解决跨域问题?

解决跨域目前有以下几种:

    1. 纯前端方式:采用JSONP;
    1. 后端配合方式:使用nginx反向代理;
    1. 小白选手方式:修改谷歌浏览器的配置;
    1. 本地调试方式:本地搭建一个服务。

针对这一次案例:本地脚本读取本地json文件。其实只要案例项目放到服务器中,避免掉使用file:///协议访问页面,就不是跨域了。

如果一定要在本地打开,要么是方案4-本地起一个服务;要么就是方案1-jsonp

此处我们着重看下怎么使用jsonp解决跨域。

四、JSONP方式解决跨域问题

1. 什么是jsonp?

JSONP是一种非正式传输协议,目的就是便于客户端使用数据。它的具体概念和优点,请查看参考文章3.
要注意区分jsonjsonp两个概念:

  • json : 是一种数据格式。
  • jsonp: 是一种数据调用方式。

JSONP方式具有一定的局限性:

  • 仅适用于GET请求;
  • 读取本地json文件的话,json文件里的数据要包含在一个函数名里(这个往后看就知道是什么意思了)。

1. 实现原理

我们知道,<script> 标签是不受同源策略的限制的,它可以载入任意地方的 JavaScript 文件,而并不要求同源(回忆下,我们可以通过<script> 载入官方服务器(或者cdn)上的一些库文件,比如jq库文件或者boostrap库文件)。
所以,我们可以利用<script> 标签的这个特点,用它来载入json文件。

载入json文件后,我们还需要获取到文件里面的json数据,这时候我们可以借用函数调用方式,把json数据作为函数实参,从而在js代码中取到数据。

2. 实现步骤

step1: 定义一个函数getJson(),这个函数将会在.json文件里被调用,得到json数据。可以在函数内部对json数据处理。

step2: 通过<script>标签引入test.json文件。

step3: test.json文件中,要把json数据作为实参放在函数getJson()中,即调用函数。

<!-- demo.html -->

<script type="text/javascript">
// 1. 定义接收数据的函数
    function getJson(data){
                // data 就是要取的json数据
        console.log(data);
        alert(data.name);
                
              // 可以在函数内部对json数据进行处理
    }
</script>

<!-- 2. 引入json文件 -->
<script type="text/javascript" src="test.json"></script>

// test.json

// 3. 真正json数据需要放在函数getJson()里,相当于作为调用函数getJson的实参。
getJson({
    "name": "celine",
    "nickName": "bling",
    "likes": [
        {
            "name": "Alex",
            "age": "18"
        },
        {
            "name": "Didi",
            "age": "9"
        }
    ]
})

网络上有些提到在引入json文件时候,需要在链接后面加上回调函数,如下:

<script type="text/javascript" src="test.json?callback=getJson">

这种一般是向服务器请求json文件时,允许客户端传递一个callback参数(此处就是getJson)给服务端,然后服务端返回数据时会将这个callback参数(即getJson)作为函数名来包裹住JSON数据,这样客户端就可以随意定义自己的函数来处理返回数据了。——这也是JSONP协议的要点。
也就是说,json文件不需要手动去给它包裹上一个函数名了(即不需要上面的step3,这个步骤由后端返回数据时完成)。

五、结语

以上就是一个jsonp方式解决跨域问题的方案。
但这种需要去修改json文件里面的原始数据结构,其实也不是很好。
希望有更好方案,小伙伴可以积极提供。

思考:vue-cli项目中,因为有一个本地服务器概念,如果使用axios去请求json文件,不知道是不是就没有跨域问题了。有待尝试!
甚至有可能直接用import或者require就可以获取到呢?

参考文章:

  1. 谷歌通过ajax获取本地JSON文件,为什么会提示跨域?
    杂糅了一大堆的资料,后面的例子反而不是和清晰了。
  2. 解决ajax不能访问本地文件(利用js跨域原理)
    通过截图,很清晰说明了jsonp应用过程。
  3. jsonp 读取本地文件
    这篇的主要贡献是:介绍了jsonp的概念、提出jsonp的有点,与ajax的区别。很建议一读!

相关文章

  • jsonp解决js读取本地json跨域问题

    一 、问题描述 通过ajax方式读取本地json文件,谷歌浏览器会提示跨域错误,导致获取不到json数据。 aja...

  • 谷歌浏览器获取本地json文件跨域问题及JSONP的应用

    最近需要读取本地json文件,找到了原生js方式和ajax方式,都会报跨域的问题。于是研究了下什么是跨域,为什么会...

  • 前端必备HTTP技能之JSONP技术详解

    JSONP(JSON with Padding)是一种JSON扩展,用来解决由浏览器同源策略引起跨域限制。跨域限制...

  • 本地调试报 跨域请求的问题

    本地调试 谷歌浏览器报错:跨域问题处理 Access-Control-Allow-Origin 在谷歌中实现数据跨...

  • JSONP详解

    JSONP是json的一种使用模式,可以让网页从别的域名那获取资料,即跨域读取资料。 AJAX请求普通文件存在跨域...

  • JSONP跨域

    JSONP 全称:JSON with Padding,可用于解决主流浏览器的跨域数据访问的问题。 通过script...

  • json和jsonP的区别:

    json是一种轻量级的数据交换格式,jsonP是解决跨域问题的一种获取数据的方式;json是协议,jsonP是使用...

  • Ajax请求跨域问题

    遇到ajax请求跨域问题,解决方式,改dataType为jsonp json和jsonp返回数据格式json格式 ...

  • 跨域的解决方式

    1.JSONP(JSON with Padding)可用于解决主流浏览器的跨域数据访问的问题。由于Web 页面上调...

  • 对jsonp 的理解认识

    什么是跨域?为什么要跨域呢?听说jsonp能. 为什么jsonp能跨域呢?什么时候使用jsonp?怎么使用json...

网友评论

    本文标题:谷歌浏览器获取本地json文件跨域问题及JSONP的应用

    本文链接:https://www.haomeiwen.com/subject/seroihtx.html