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

最近需要读取本地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. 实现原理

我们知道,

// test.json

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

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


                    
                    

你可能感兴趣的:(谷歌浏览器获取本地json文件跨域问题及JSONP的应用)