让前端飞jsWeb前端之路

JSONP原理(2018-08-16)

2018-08-16  本文已影响1人  CRUD_科科
为什么会有跨域问题存在

     因为浏览器的同源策略(协议,端口,域名任何一个不同,同源策略都会禁止跨域),原来是浏览器再giao事情:同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

正确展开跨域的几种方式

     同源策略是浏览器做的一件好事,是用来防御来自邪门歪道的攻击,但是不能吧我们自己人也挡在门外,这时候就需要正确的打开方式:

server{
    
# 监听9099端口
    listen 9099;
    
# 域名是localhost
    server_name localhost;
    
#凡是localhost:9099/api这个样子的,都转发到真正的服务端地址http://localhost:9871 
    location ^~ /api {
        proxy_pass http://localhost:9871;
    }   
}
跨域Dom查询

     参考:https://mp.weixin.qq.com/s/Ldh6rkcimZ1ppHPHK3KeUQ

JSONP的工作流程
封装jsonp
/**
 * JSONP handler
 *
 * Options:
 *  - param {String} qs parameter (`callback`)
 *  - prefix {String} qs parameter (`__jp`)
 *  - name {String} qs parameter (`prefix` + incr)
 *  - timeout {Number} how long after a timeout error is emitted (`60000`)
 *
 * @param {String} url
 * @param {Object|Function} optional options / callback
 * @param {Function} optional callback
 */
// url要请求的地址以及拼接的参数;opts{param: 约定的函数参数,timeout:超时时间,name:指定的函数名,prefix:指定的函数名前缀};fn回调函数
var count = 0
function noop(){}
function jsonp(url, opts, fn) {
 // opts 如果是一个函数 赋值给fn 并重置opts为空对象
    if('function' == typeof opts){
        fn = opts
        opts = {}
    }
   // 如果没有opts 给opts赋值空对象
    if(!opts) opts = {}
    var prefix = opts.prefix || '__jp'
    // id为opts的name或者prefix+计数(prefix为opts.prefix或__jp)
    var id = opts.name || (prefix + (count++))
    var param = opts.param || 'callback'
    // 有opts.timeout 就取 没有就是60000ms
    var timeout = null != opts.timeout ? opts.timeout : 60000
    var enc = encodeURIComponent
    // 第一个script或者head标签
    var target = document.getElementsByTagName('script')[0] || document.head
    var script
    var timer
    // 如果有timeout就在timeout之后执行clean并抛出Error
    if (timeout) {
        timer = setTimeout(function(){
            cleanup()
            if(fn) fn(new Error('Timeout'))
        }, timeout)
    }
    function cleanup() {
        // 移除创建的script 回调函数置空 清除定时器
        if(script.parentNode) script.parentNode.removeChild(script)
        window[id] = noop
        if(timer) clearTimeout(timer)
    }
    function cancel() {
        if(window[id]) {
            cleanup()
        }
    }
    // 全局挂载id
    window[id] = function(data) {
        cleanup()
        // 请求返回后执行回调fn
        if(fn) fn(data)
    }
    url += (~url.indexOf('?') ? '&' : '?') + param + '=' + enc(id);
    url = url.replace('?&', '?');
    // 创建script标签src属性赋值url
    script = document.createElement('script')
    script.src = url;
    // 插入到head或script的前面
    target.parentNode.insertBefore(script, target);
    return cancel;
 }

此方法在调用时需要自己拼接将参数拼接在url后面 opts如果跟后台有约定callback参数名就传{param: 约定参数名} ,没有默认callback

上一篇下一篇

猜你喜欢

热点阅读