跨域的解决方式

跨域取值的本质是服务器返回一个函数的调用

很多情形下我们都需要去查询其他服务器的参数,这时候都是跨域的,虽然说ajax是不支持跨域的,但是js是可以跨域取值的,比如我们可以通过javaScript标签中的src属性跳转到其他服务器去获取数据。

跨域取值简单来说就是被访问的服务器返回一个当前服务器中已经定义的函数的调用。举例来说就是在当前js中定义一个函数,然后在访问的服务器(跨域了)中执行之前定义的函数。通过这个函数的参数将我们想要的数据得到。在我们使用淘宝的时候都有这样的经历,当我们在搜索栏输入一个词,就会立即返回与这个词相关的词条,现在就使用淘宝的接口在我们自己的js页面来实现输入一个词获取淘宝的返回数据,这是访问淘宝的服务器,所以肯定是跨域访问。

看下面的html文件的代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    window.onload = function () {
        var btn = document.querySelector("#btn");
        btn.onclick = function(){
            var keywordValue = document.querySelector("#keyword").value;
            var script = document.createElement("script");
            script.src = "https://suggest.taobao.com/sug?q="+keywordValue+"&callback=testFunction"
            window["testFunction"] = function (data) {
                var liTag = "";
                for (var i = 0; i < data.result.length; i++){
                    var temp = data.result[i];
                    var tempSug = temp[0];
                    liTag += "<li>"+ tempSug +"</li>"
                }
                var ulTag = document.querySelector("ul");
                ulTag.innerHTML = liTag;
            };
            var head = document.querySelector("head");
            head.appendChild(script);
        }
    }
</script>
<input type="text" id="keyword" placeholder="请输入关键字"/>
<input type="button" id="btn" value="查询"/>
<ul>
    <li></li>
    <li></li>
    <li></li>
</ul>
</body>
</html>

上面的例子中就是只有一个js入口函数,有一个输入框和查询按钮,下面的ul主要是为了显示我们的返回的数据。

其中淘宝给定的接口形式是 https://suggest.taobao.com/sug?q=参数1&callback=参数2,这里我们需要传入的有两个参数,第一个是我们输入的需要查询的关键词,地的歌就是回调函数,因为要动态的传入参数,所以不是写了一个固定的script标签,而是动态创建了一个script标签,然后给这个标签src属性赋值,这样就可以达到动态传递参数的效果。

window["testFunction"] = function (data) {
    var liTag = "";
    for (var i = 0; i < data.result.length; i++){
        var temp = data.result[i];
        var tempSug = temp[0];
        liTag += "<li>"+ tempSug +"</li>"
    }
    var ulTag = document.querySelector("ul");
    ulTag.innerHTML = liTag;
};

上面的代码中window[“testFunction”] = function(){}其实就是给window加上一个参数,这个参数就是我们传递的回调函数。这一句的作用其实就是我们上面所说的在本服务器(发出请求的那个域)里面先定义好的函数,和下面的代码作用是一样:

<script>
    function testFunction(data) {
        //这里的data就是从淘宝服务器查询后传回来的数据
    }
</script>

最后就是处理获取的结果,将其显示在页面中。
查询结果如下图:
跨域的解决方式

解决在ajax中不能跨域获取数据的问题

使用jquery封装的ajax时其实是可以跨域获取数据的,使用ajax的语法是$.ajax({name:value, name:value, … }),
如果要跨域访问数据,则需要关注下图中的几个参数。
跨域的解决方式
上面标红的参数中dataType是必须的参数,正常情况下我们使ajax时datatype参数一般是使用json或者是xml格式,使用这种方式是不能实现跨域访问数据的,只有将datatype的值设置为jsonp时才可以实现跨域获取服务器的数据。
jsonp与jsonpCallback这两个参数不是必须的。
实际上当dataType为jsonp时使用ajax去获取的本质不是通过下面的方式去获取数据的:

var xhr = new XMLHttpRequest();
xhr.open("get", url, true);
xhr.send(null);
xhr.onreadystatechange = function(){}

通过这种方式是不能跨域访问的,但可以通过script标签中的src属性跳转到到某一个跨域的服务器获取数据,所以通过jquery封装的ajax实现跨域获取数据时本质上也是通过动态创建script标签,并且动态的给这个script标签的src属性赋值来传递我们的参数给服务器并且获取数据。

解决跨域方式的不足

上面已经说过这种解决跨域的方式的本质是服务器返回一个方法的调用,但是很多时候我们访问第三方服务器的接口时返回的是一个json格式的字符串,此时使用这种方式是没有用的,而且使用ajax的四个步骤也是没有用的。所以如果第三方接口返回的不是方法的调用而是json格式的字符串的时候就需要使用另外一种方式,就是我们通过正常的ajax去访问我们自己的服务器,在自己的服务器中去获取第三方服务器的数据,将获取到的json格式的字符串返回给前端即可。即是将自己的服务器做一个中转。