ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ajax跨域、jsonp原理

2020-08-12 15:31:16  阅读:269  来源: 互联网

标签:跨域 param xhr ajax defaults jsonp var data


Ajax跨域

  • 同源策略

    • 同源策略是浏览器的一种安全策略,所谓同源指的是请求URL地址中的协议、域名和端口都相同,只要其中之一不相同就是跨域。

    • 同源策略主要为了保证浏览器的安全性。

    • 在同源策略下,浏览器不允许Ajax跨域获取服务器数据。

http://www.example.com/detail.html

说明
http://api.example.com/detail.html 域名不同
https://www.example.com/detail.html 协议不同
http://www.example.com:8080/detail.html 端口不同
http://api.example.com:8080/detail.html 域名、端口不同
https://api.example.com/detail.html 协议、域名不同
https://www.example.com:8080/detail.html 端口、协议不同

跨域解决方案

  • jsonp (仅仅是get请求方式)

  • document.domain+iframe

  • location.hash + iframe

  • window.name + iframe

  • window.postMessage

  • flash等第三方插件

jsonp 原理

  • 静态script标签的src属性进行跨域请求

    <script src="http://www.ajaxDemo.cc/check.php"></script> <!-- 同步加载 -->
    <!--<script src="http://www.ajaxDemo.cc/check.php" async></script>--> <!-- async 异步加载 -->
    <script >
        /*
            这种方式存在的两个主要的问题:
            1、必须保证加载的顺序
            2、不方便通过程序传递参数
            */
        console.log(data)
    </script>
    
    
  • 动态创建script标签,通过标签的src属性发送请求(异步请求)

    <script>
        var script = document.createElement('script');
        script.src = 'http://www.ajaxDemo.cc/check.php?callback=foo';
    
        var head = document.getElementsByTagName('head')[0];
        head.appendChild(script);
    		
        function foo(data){
            console.log(data)
        }
    </script>
    
    // check.php
    $cb = $_GET['callback'];
    $data = '{"code":"2","msg":"登录失败"}';
    echo "$cb($data)";
    

原理:

动态创建script标签,然后通过它的src属性发送跨域请求,然后服务器端响应的数据格式为【函数调用(foo(实参))】,所以在发送请求之前必须先声明一个函数(foo),并且函数的名字与参数中传递的名字要一致。这里声明的函数是由服务器响应的内容(实际就是一段js代码-函数调用)来调用。

  • 需要注意的是,callback参数定义是需要前后端定义好的,具体什么名字,商讨好就可以了

jQuery 对 jsonp 的支持

$.ajax({
    url: 'http://www.ajaxDemo.cc/check.php',
    type:'get',
    dataType: 'jsonp', //指定服务器返回的数据类型
    jsonp:'cb', //指定参数名称,默认是callback
    jsonpCallback:'abc', //指定回调函数名称,默认是 "jQuery" + ( version + Math.random() ).replace( /\D/g, "" )+当前时间毫秒数
    data:{},
    success: function(res){
        console.log(res)
    },
    error:function(err){
        console.log(err)
    }
})

jsonp 接口

  • 基于jsonp的常见功能

    • 搜索智能提示

    • 快递查询

  • 第三方接口介绍(json/jsonp)

模拟 jQuery jsonp封装可跨域请求

function ajax(obj){
    var defaults = {
        type : 'get',
        async : true,
        url : '#',
        dataType : 'text',
        jsonp : 'callback',
        data : {},
        success:function(data){console.log(data);}
    }

    for(var key in obj){
        defaults[key] = obj[key];
    }

    if(defaults.dataType == 'jsonp'){
        ajax4Jsonp(defaults);
    }else{
        ajax4Json(defaults);
    }
}

function ajax4Json(defaults){
    // 1、创建XMLHttpRequest对象
    var xhr = null;
    if(window.XMLHttpRequest){
        xhr = new XMLHttpRequest();
    }else{
        xhr = new ActiveXObject('Microsoft.XMLHTTP');
    }
    // 把对象形式的参数转化为字符串形式的参数
    /*
    {username:'zhangsan','password':123}
    转换为
    username=zhangsan&password=123
    */
    var param = '';
    for(var attr in defaults.data){
        param += attr + '=' + defaults.data[attr] + '&';
    }
    if(param){
        param = param.substring(0,param.length - 1);
    }
    // 处理get请求参数并且处理中文乱码问题
    if(defaults.type == 'get'){
        defaults.url += '?' + encodeURI(param);
    }
    // 2、准备发送(设置发送的参数)
    xhr.open(defaults.type,defaults.url,defaults.async);
    // 处理post请求参数并且设置请求头信息(必须设置)
    var data = null;
    if(defaults.type == 'post'){
        data = param;
        xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    }
    // 3、执行发送动作
    xhr.send(data);
    // 处理同步请求,不会调用回调函数
    if(!defaults.async){
        if(defaults.dataType == 'json'){
            return JSON.parse(xhr.responseText);
        }else{
            return xhr.responseText;
        }
    }
    // 4、指定回调函数(处理服务器响应数据)
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4){
            if(xhr.status == 200){
                var data = xhr.responseText;
                if(defaults.dataType == 'json'){
                    // data = eval("("+ data +")");
                    data = JSON.parse(data);
                }
                defaults.success(data);
            }
        }
    }
}
function ajax4Jsonp(defaults){
    // 这里是默认的回调函数名称
    // expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
    var cbName = 'jQuery' + ('1.11.1' + Math.random()).replace(/\D/g,"") + '_' + (new Date().getTime());
    if(defaults.jsonpCallback){
        cbName = defaults.jsonpCallback;
    }

    // 这里就是回调函数,调用方式:服务器响应内容来调用
    // 向window对象中添加了一个方法,方法名称是变量cbName的值
    window[cbName] = function(data){
        defaults.success(data);//这里success的data是实参
    }

    var param = '';
    for(var attr in defaults.data){
        param += attr + '=' + defaults.data[attr] + '&';
    }
    if(param){
        param = param.substring(0,param.length-1);
        param = '&' + param;
    }
    var script = document.createElement('script');
    script.src = defaults.url + '?' + defaults.jsonp + '=' + cbName + param;
    var head = document.getElementsByTagName('head')[0];
    head.appendChild(script);
}

基本使用:

ajax({
    url:'',
    type:'get',
    data:{},
    dataType:'jsonp'
    success: function(res){
    	console.log(res)
	}
})

标签:跨域,param,xhr,ajax,defaults,jsonp,var,data
来源: https://www.cnblogs.com/vicky123/p/13490838.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有