美文网首页
jsonp原理和实现

jsonp原理和实现

作者: 高级程序狗 | 来源:发表于2020-01-27 16:38 被阅读0次

是时候彻底搞清jsonp了!

jsonp主要是利用了脚本不受 同源策略 限制的"BUG",算是一种简单的hack写法,主要分3个步骤:

1.前端请求一个脚本,注意这里是 脚本 而不是ajax。通常是动态创建一个script标签,文件的地址就是异步地址,但是会带一个callback参数(也可以和后端商量约定)https://xxx.com/api/getsth?callback=__jsonp1234,callback参数的值是唯一的,用来区分不同的请求。

  //ps:如果不需要接收response,比如埋点统计,甚至可以创建一个image
  var target = document.getElementsByTagName('script')[0] || document.head;
  var script;
  script = document.createElement('script');
  script.src = url;//这里的url实际就是异步地址
  target.parentNode.insertBefore(script, target);

2.后端需要配合前端做下兼容:

//假设要返回的数据是:{name:'wyz',age:18}
var data = {name:'wyz',age:18};

if(req.query.callback){
    //当发现前端传了callback参数
    //实际输出:__jsonp1234({name:'wyz',age:18})
    res.send(`${req.query.callback}(${data})`)
}else{
    //没传callback正常返回即可
    res.json(data)
}

3.页面加载完成这个脚本后,相当于在创建script标签的位置调用了__jsonp1234({name:'wyz',age:18})方法。如果在请求之前,已经创建好了全局方法window.__jsonp1234 = function(data){console.log(data)}呢?

<html>
<head>
</head>
<body>
    <!--...-->


    <!--这个是动态创建的-->
    <script src="https://xxx.com/api/getsth?callback=__jsonp1234"></script>
    <!--加载完成后,相当于:-->
    <!-- <script>
        __jsonp1234({name:'wyz',age:18})
    </script> -->

    <script>
        var target = document.getElementsByTagName('script')[0] || document.head;
        var script;
        script = document.createElement('script');
        script.src = "https://xxx.com/api/getsth?callback=__jsonp1234";
        target.parentNode.insertBefore(script, target);
        window.__jsonp1234 = function (data) {
            console.log(data)//当请求完成,调用了__jsonp1234方法,这里就会打印出来
        }
    </script>
</body>
</html>

是不是so easy?趁热打铁,附上一个jsonp的实现源码:

/**
 * Module dependencies
 */

var debug = require('debug')('jsonp');//这个debug插件晚点有空研究一下

/**
 * Module exports.
 */

module.exports = jsonp;

/**
 * Callback index.
 */

var count = 0;

/**
 * Noop function.
 */

function noop(){}

/**
 * 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
 */

function jsonp(url, opts, fn){
  if ('function' == typeof opts) {
    fn = opts;
    opts = {};
  }
  if (!opts) opts = {};

  var prefix = opts.prefix || '__jp';

  // use the callback name that was passed if one was provided.
  // otherwise generate a unique name by incrementing our counter.
  var id = opts.name || (prefix + (count++));

  var param = opts.param || 'callback';
  var timeout = null != opts.timeout ? opts.timeout : 60000;
  var enc = encodeURIComponent;
  var target = document.getElementsByTagName('script')[0] || document.head;
  var script;
  var timer;


  if (timeout) {
    timer = setTimeout(function(){
      cleanup();
      if (fn) fn(new Error('Timeout'));
    }, timeout);
  }

  function cleanup(){
    if (script.parentNode) script.parentNode.removeChild(script);
    window[id] = noop;
    if (timer) clearTimeout(timer);
  }

  function cancel(){
    if (window[id]) {
      cleanup();
    }
  }

  window[id] = function(data){
    debug('jsonp got', data);
    cleanup();
    if (fn) fn(null, data);
  };

  // add qs component
  url += (~url.indexOf('?') ? '&' : '?') + param + '=' + enc(id);
  url = url.replace('?&', '?');

  debug('jsonp req "%s"', url);

  // create script
  script = document.createElement('script');
  script.src = url;
  target.parentNode.insertBefore(script, target);

  return cancel;
}

相关文章

  • jsonp原理和实现

    是时候彻底搞清jsonp了! jsonp主要是利用了脚本不受 同源策略 限制的"BUG",算是一种简单的hack写...

  • day02-vuejs-vue-resource实现get, p

    vue-resource实现get, post, jsonp]请求: JSONP的实现原理: 由于浏览器的安全性限...

  • vue音乐APP03:jsonp promise化

    1.JSONP的用途和原理 使用JSONP主要是目的通过动态创建Script,动态拼接url,进而抓取数据,实现跨...

  • 遇到的面试题

    null instanceOf Object false jsonp跨域原理,优缺点,安全性因素 jsonp的实现...

  • 跨域方案

    JSONP JSON with padding 简称JSONP ,实现原理 通过动态 元素,指定src属性为一个跨...

  • JSONP的历史方案和实现原理

    1. JSONP的实现原理 JSONP是通过动态创建script实现的。请求方:frank.com 的前端程序员(...

  • 跨域

    解决跨域方法:jsonp,代理,cors jsonp实现原理:动态创建script标签 ,因为script中的sr...

  • JSONP实现原理

    JSONP:JSON With Padding 含义:可以理解为请求后端API,服务器会在传给浏览器前将JSON数...

  • JSONP

    1.jsonp是用来实现跨域通信的一种方法。原理如下: 2.jsonp实现过程: 大家的约定为: callback...

  • 手写一个JSONP(promise封装)

    前言 JSONP以前研究过,最近又有点忘了,写篇本文mark一下,旨在理解记住JSONP的原理及其实现。代码实现用...

网友评论

      本文标题:jsonp原理和实现

      本文链接:https://www.haomeiwen.com/subject/uzdethtx.html