跨域请求,jsonp封装

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。(同源策略主要针对域名host,端口号part)通俗来讲,因为安全原因 服务器只允许浏览器在本域下的文档资源,若非本域访问,则会产生跨域。

一、跨域案例

1.通过Node构建两个web服务器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d3nXDSkq-1583619489349)(/static/upload/article/1582568810116.png)]
2.将页面挂载到服务器1

let http = require('http');
let fs = require('fs');
http.createServer((req,res)=>{
    //创建服务1  将index.html挂载到服务器
    fs.readFile("./index.html",(err,data)=>{
        if(err) throw err;
        res.end(data);
    })
}).listen(1111);
//挂载到http://localhost:1111 
console.log("success port1111");

3.创建服务器2模拟跨域请求

let http = require('http');
http.createServer((req,res)=>{
   res.end("这是服务器2中的文本")
}).listen(2222);
///挂载到http://localhost:2222 
console.log("success port2222");

4.结果
在这里插入图片描述
提示请求跨域,因为网页挂载在http://localhost:1111下,而页面向服务器2http://localhost:2222
中提交了一个get请求,他们不在同一个域下,违反了同源安全策略,即是一个跨域请求。

二、解决方法

目前常用的两种方式是CORS与JSONP;

  1. CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。
  • 普通跨域请求:只需服务器端设置Access-Control-Allow-Origin请求头即可
  • 带cookie跨域请求:前后端都需要进行设置
let http = require('http');
http.createServer((req,res)=>{
    res.writeHead(200,{
        "Content-Type":"text/plain",
        "Access-Control-Allow-Origin":"http://localhost:1111",
        //"Access-Control-Allow-Origin":"*"
    });
    res.end("这是服务器2中的文本")
}).listen(2222);
///挂载到http://localhost:2222 
console.log("success port2222");

Access-Control-Allow-Origin值有两种配置方式,* 代表允许所有域,填写特定域名则可放行特定域
在这里插入图片描述
获取成功,解决跨域。

  1. JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。其原理是利用script标签不受同源策略的限制,可以自由加载各类文件的特点去实现的;

请求配置

    //创建一个script标签
    let scriptTag = document.createElement("script");
    //注入请求地址  可带参数
    scriptTag.src = "http://localhost:2222/?callback=callback";
    //将创建script标签放入head中 发送请求
    document.querySelector('head').appendChild(scriptTag);
    //回调函数
    function callback(res) {
        console.log(res)
    }

服务端配置

let http = require('http');
let url = require('url');
let querystring = require('querystring');
//导入url querystring模块,解析请求参数
http.createServer((req,res)=>{
    //获取参数
    let query = querystring.parse(url.parse(req.url).query);
    //回调函数名称
    let callback = query.callback;
    console.log(callback);
    res.writeHead(200,{
        //返回数据格式一定要为js
        "Content-Type":"text/javascript;charset=UTF-8"
    });
    let data = { //定义返回数据
        code:200,
        msg:"这是一段文字!"
    };
    //发送数据包
    res.end(`${callback}(${JSON.stringify(data)})`)
}).listen(2222);
console.log("success 2222");

在这里插入图片描述

在这里插入图片描述
请求成功,callback函数调用成功
JSONP实际上就是前端页面通过创建script标签形成跨域请求,并在页面中编写回调函数并将函数名传递给后端,等待后端响应,以 func(传参);调用的方式将数据通过js的方式返回到创建的script标签中,而返回数据被浏览器编译为js代码,到达页面后立即调用回调函数完成请求;
三、JSONP请求封装
创建一个jsonp请求的步骤相对较多,我用Promise做了一个简单的封装

代码封装
    function jsonp(option){
        return new Promise((resolve,reject)=>{
            //创建一个script标签
            let scriptTag = document.createElement("script");
            //定义数据段
            let query = '?';
            //数据段拼接
            for (key in option.data){
                query += key + '=' +option.data[key] +'&'
            }
            //回调函数名拼接
            query += 'callback=' + option.callbackName;
            //填写src
            scriptTag.src = option.url + query;
            //插入到head中 发送请求
            //动态创建callback
            window[option.callbackName] = res => {
                //请求jsonp接口成功后,删除该函数 - 不污染window
                delete window[option.callbackName];
                //删除请求接口时动态创建的script标记
                document.head.removeChild(scriptTag);
                //判断接口的数据返回
                if (res) {
                    resolve(res);
                } else {
                    reject("服务器没有返回数据");
                }
            };
            //发送请求  一定要在动态创建回调函数后发送  所以放在最后
            document.querySelector('head').appendChild(scriptTag);
        })
    }
调用方法
jsonp({
    url:'http://localhost:2222',
    data: {
    },
    callbackName:'callback'
}).then(res=>{
    //成功方法
}).catch(res=>{
    //未成功方法
})

这样用起来是不是简单很多呢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值