天天看点

node.js第三天-----ajax(2)

跨域请求

什么是跨域请求

         浏览器为了安全性问题,做出了同源策略的限制,跨域请求是不能请求的。什么是域:域就是协议名和主机名+端口号。只有三部分都一样才能说是相同的域。相同域之间不受限制,不同域之间不能相互请求。

如何处理跨域请求

          jsonp处理跨域请求,跨域请求很多常见的是jsonp。

         平时用的<img>,<link>,<script>这些标签是不受跨域限制的。但是能不能让<script>去请求数据来请求获取json数据呢?答案是肯定的。json可以描述复杂的数据。更重要的是json格式的数据能被JavaScript原生支持。于是服务器端就可以生成json文件。这样一种解决跨域请求的方案就出来了,大家称之为jsonp。

          请看一下代码

// 服务器
// jsonp跨域
app.get('/3-6-2-json-1.js',function(req,res){
  res.render('3-4-1-post');
});


//3-6-2-json-1.js
alert('the message from server');

//jsonp.html
<!DOCTYPE html>
<html>
<head>
  <title>jsonp</title>
  <meta charset="utf-8">
</head>
<body>
  <script type="text/javascript" src="http://localhost:3000/3-6-2-json-1.js"></script>
</body>
</html>      

       接下来扩展一下

// jsonp1.html
<!DOCTYPE html>
<html>
<head>
  <title>jsonp</title>
  <meta charset="utf-8">
</head>
<body>
  <script type="text/javascript">
    function getData(data){
      alert("我是本地函數,跨域請求服務器的js文件,服務器返回是:"+data.result);
    }
  </script>
  <script type="text/javascript" src="http://localhost:3000/3-6-2-json-1.js"></script>
</body>
</html>

// 3-6-2-json-1.js
getData({result:'this message from server'});      

      这样跨域就可以使用了,但是有一个问题就是如何让服务器知道本地的函数名?可以在url后传递参数

封装jsonp

function getData(data){
            alert("我是本地函數,跨域請求服務器的js文件,服務器返回是:"+data.result);
        }
        // 封装jsonp url 请求的url callback回调
        ajax.jsonp = function(){
            // 创建动态的script标签
            var script = document.createElement('script');
            // 生成函数名
            var time = new Date();
            var funcName = 'jsonp' + time.getTime();
        }

        // 拼接url,判断url中是否有参数
        if(url.indexOf('?')>0){
            url = url + '&callback=' + funcName;
        }else{
            url = url + '?callback=' + funcName;
        }

        // 注册回电函数到全局
        window[funcName] = function(data){
            callback(data);
            delete window[funcName];
            script.parentNode.removeChild(script);
        }

        // 设置script标签的src属性
        script.setAttribute('src',url);
        // 把script 标签加入到head,请求服务得到数据
        document.getElementsByTageName('head')[0].appendChild(script);
}

//调用代码
Ajax().jsonp('http://localhost:3000/3-6-2.js?city=tj&date=20200101',function(data){
    function(data){
        alert(data.city+'在'+data.date+'天气'+data.weater);
    }
})      

基于标签

    window.name属性始终存在于当前窗口所打开过的所有页面中,不会因页面的刷新和新页面的载入而重置。

// window.name.html
<!DOCTYPE html>
<html>
<head>
    <title>window.name</title>
    <meta charset="utf-8">
</head>
<body>
    <a href="./3-6-2-iframe-2.html">点击在本窗口打开并且查看window.name的值</a>
    <script type="text/javascript">
        window.name = '这是第一个页面设置的name属性的值'
    </script>
</body>
</html>


// 3-6-2-iframe-2.html
<!DOCTYPE html>
<html>
<head>
    <title>3-6-2-iframe-2.html</title>
    <meta charset="utf-8">
</head>
<body>
    <h3>这是在本窗口贷款的第二个嗯,在这个页面显示window.name的值</h3>
    <script type="text/javascript">
        alert(window.name);
    </script>
</body>
</html>      
//windowName.html
<!DOCTYPE html>
<html>
<head>
  <title>windowName</title>
  <meta charset="utf-8">
</head>
<body>
  <button onclick="getData()">点击发起跨域请求</button>
  <iframe id="iframe" src="http://localhost:3000/3-6-2-iframe-data?name=ab" style="display: none"></iframe>
  <script type="text/javascript">
    function getData(){
      // 获取iframe标签对象
      var iframe = document.getElementById('iframe');
      iframe.src = 'about:black';
      iframe.onload = function(){
        var data = iframe.contentWindow.name;
        data = JSON.parse(data);
        alert(data.name + '的口号是:' + data.info);
      }
    }
  </script>
</body>
</html>

// 服务器
//windowName
app.get('/3-6-2-iframe-data',function(req,res){
  var param = req.query.name;
  var data = {name:param,info:'唯我独尊'};
  var data = JSON.stringify(data);
  res.send("<script>window.name='"+data+"';</script>");
});      

封装window.name跨域请求

// 封装window.name 跨域请求
    ajax.iframe = function(url,callback){
      // 创建iframe标签
      var iframe = document.createElement('iframe');
      // 设置属性为隐蔽
      iframe.style = 'none';
      // 指定iframe的src属性
      iframe.src = url;
      // 把iframe写入到body中
      document.getElementsByTageName('body')[0].appendChild(iframe);
      // 设置标志用于判断,保证src只设定一次
      var flag = true;
      // src只改变一次,iframe重新加载一次
      ajax.onload = function(){
        // 判断状态,防止重置src
        if(flag){
          // 将域设置成同城
          iframe.src = 'about:black';
          // 一旦设置好后就可以获取window.name的值了
          flag = false;
        }else{
          // 获取服务器设定name
          var data = iframe.contentWindow.name;
          // 判断用户想要接收的数据类型
          if(ajax.dataType == 'JSON'){
            // 将json格式字符串转化为json对象
            data = JSON.parse(data);
          }

          // 将数据给回调函数
          callback(data);
          // 销毁节点
          document.body.removeChild(iframe);
        }
      }
    };

    // 考虑到兼容
    if(iframe.attachEvent){
      iframe.attachEvent('onload',ajax.onload);
    }else{
      iframe.onload = ajax.onload;
    }