自定义jsonp请求数据

整理代码的时候发现一个以前写的实现jsonp请求方法,放在这里分享一下~
原理:通过js新建script dom对象,利用src携带参数和callback方法,将数据发送至后端,需要后端配合将数据放在callback中返回
功能:可以同时进行多个jsonp请求,且可以设置超时时间
注意:为了保证可以同时进行多个jsonp请求,所以每次请求需要新增script dom对象,请求结束后需要进行销毁

    var jsonpId = 0;  // 用来标记创建的<script>元素
    var debug = true;   // 是否开启debug
    function addScriptTag(src) {
      var script = document.createElement('script');
      script.setAttribute('type', 'text/javascript');
      script.setAttribute('src',src);
      script.setAttribute('onload','try {document.body.removeChild(this);} catch (e) { debug ? console.error(e) : ""; }'); // 用完就删
      document.body.appendChild(script);
      return script;
    }

    /*
     * jsonp 获取数据 跨域
     * paramObj {
     *   url: 请求的接口
     *   timeout: 请求过期时间(设置为0或者不设置这个参数,表示不设置过期时间,默认为0)
     *   data: 要发送的数据
     *   ready: 请求成功后调用的方法
     *   error: 请求失败后调用的方法(如:超时)
     * }
     * */
    function jsonpData(paramObj) {
      var url = paramObj.url + ((paramObj.url.indexOf('?') > -1) ? '&' : '?') + formatParams(paramObj.data);
      // 请求数据
      var mark = jsonpId++;
      window.jsonpCallback ? true : window.jsonpCallback = {};
      window.jsonpCallback[mark] = function (data) { // 针对每一个jsonp请求,生成一个对应的callback方法
        clearTimeout(window.timer[mark]);  // 清除掉对应的定时器

        paramObj.ready ? paramObj.ready(data) : '';

        try { // 删除回调方法
          delete window.jsonpCallback[mark];
        } catch (e) {
          window.jsonpCallback[mark] = null;
        }
      };
      var script = addScriptTag(url + "&callback=jsonpCallback[" + mark + "]");

      // 请求超时处理
      var timeout = paramObj.timeout ? paramObj.timeout : 0;
      window.timer ? true : window.timer = {};
      if(timeout) {
        window.timer[mark] = setTimeout(function () {
          if(window.jsonpCallback[mark]) {  // 移除对应的script dom,解决当数据超过设置的超时时间后返回了数据,但callback却不存在的情况
            try {
              document.body.removeChild(script);
            } catch (e) {
              debug ? console.error(e) : '';
            }

            window.jsonpCallback[mark] = function () {  // 重新定义一下回调方法, 改写 callback
              try {
                delete window.jsonpCallback[mark];
              } catch (e) {
                window.jsonpCallback[mark] = null;
              }
            };
            paramObj.error ? paramObj.error('请求超时,请检查网络环境!') : '';  // 超时执行 error

            // 设置一个足够长的计时器,将上面的回调方法彻底删除,如果没有走超时处理的方法,这个计时器也就不会存在
            var longTimer = setTimeout(function () {
              if(window.jsonpCallback[mark]) {   // 如果回调方法存在,彻底删除
                try {
                  delete window.jsonpCallback[mark];
                  clearTimeout(longTimer);
                } catch (e) {
                  window.jsonpCallback[mark] = null;
                }
              }
            }, 120000);
          }
          clearTimeout(window.timer[mark]);  // 清除掉对应的定时器
        }, timeout);
      }
    }

本文链接:https://www.cnblogs.com/xsilence/p/10794840.html

posted @ 2019-04-30 11:27  silencetea  阅读(984)  评论(0编辑  收藏  举报