jsonp封装浅析
来源:互联网 发布:关注足球淘宝在哪 编辑:程序博客网 时间:2024/06/05 16:28
jsonp封装浅析
前几天写项目,在获取数据时候,不想再去手写一遍jsonp,于是就上git上找了找,安装了下来,还算好用吧。今天抽出时间,看着源码也不长,就把源码给分析分析,毕竟分析好的源码是进阶的必要。
先贴上官方源码
/** * Module dependencies */var debug = require('debug')('jsonp');/** * 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;}
md文件,支持npm等多种安装安装方式。
mudule.export = jsonp//将jsonp函数导出去,供其他模块调用
安装node.js的debug模块
var debug = require('debug')('jsonp');//当般在nodejs需要进行调试的时候,可以使用console.log()方法来将调试信息输出到控制台,当发布到生产环境的时候,需要将这些调试信息都注释掉,为了方便切换而不需要改动程序代码,可以使用nodejs的debug模块,简单来说就是用来向控制台抛出错误信息的。eg: debug('jsonp got', data);
关键函数jsonp函数
接受三个参数,分别是url,opts,fn.
url:请求地址的url,eg:http://freegeoip.net/json/?callback=handleResponse
opts:有如下四个可选参数
* params 与后端约定请求的字段名称,默认是callback
* timeout 指定请求响应时间,过多长时间之后显示请求超时
* prefix 指定回调函数params的回调句柄前缀,默认为__jp,一般都是默认的,基本用不到
* name 指定回调函数的句柄,默认为’_jp${number++}’,一般都是默认的,基本用不到
fn 请求事件的回调函数,负责接受data响应数据和请求失败的err信息。
初始化参数
function jsonp(url, opts, fn){ // 对于两个参数,若不写opts,内部会将函数继续赋给fn if ('function' == typeof opts) { fn = opts; opts = {}; } // 判断opts是否存在,若不存在,将opts设置空对象 if (!opts) opts = {}; // 默认回调函数句柄为__jp var prefix = opts.prefix || '__jp'; // 默认回调函数的句柄为__jp+数字 count默认为0 var id = opts.name || (prefix + (count++)); // 设定和函数的key:value,默认为'callback:__jp01' var param = opts.param || 'callback'; // 设定请求响应时间,若没有设置,则默认为6秒 var timeout = null != opts.timeout ? opts.timeout : 60000; var enc = encodeURIComponent; // 捕获dom元素 var target = document.getElementsByTagName('script')[0] || document.head; // 声明script和timer,script是后面document.createElement出来的,timer是定时器 var script = null; var timer = null;
url字符串拼接和script脚本dom操作
// 检测是url是否有参数,如果有参数的话,也有传进来的param参数的话,那就把参拼接到url后面,而后面的enc(id)值就是key:value索要解析到的值,服务端进行**params.opts.param**进行解析调用下面这句id的方法 url += (~url.indexOf('?') ? '&' : '?') + param + '=' + enc(id); // 防止拼接错误出现"?&",然后进行替换 url = url.replace('?&', '?'); // 方便调试,这个可以将url console.log()到控制台上 debug('jsonp req "%s"', url); // 创建<script>标签,不受限制的从其它域加载资源 script = document.createElement('script'); script.src = url; // 插入到head节点或者第一个<script>节点的前面 target.parentNode.insertBefore(script, target); return cancel;
方法的调用和事件释放
// 进行超时设置,如果超时,那么清除掉原有创建的<script>标签,并且将window[id]=noop(空对象),终止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); }// 在引入jsonp模块后,取消对jsonp的调用,但引用模块值外就得这样写 eg:jsonp(yrl,opts,fn)() function cancel(){ if (window[id]) { cleanup(); } } // 服务端解析params.param进行调用函数 window[id] = function(data){ debug('jsonp got', data); // 恢复初始值 cleanup(); //返回数据 if (fn) fn(null, data); };
个人角度总结
- 无污染,无公害,用完即走
- 支持多种安装方式
- 可以结合promise进行使用
如有错误,敬请指出,共同进步。
阅读全文
0 0
- jsonp封装浅析
- jsonp封装
- Jsonp封装
- 封装一个JSONP方法
- ajax 、jsonp 、Promise 封装
- jsonp的封装
- JSONP操作02_jQ-jsonp操作_封装jsonp
- JSONP跨域原理浅析
- 原创 javascript 封装jsonp 请求
- 封装jsonp跨域请求
- 四十、vue中封装jsonp
- ajax 封装函数 jsonp处理
- 2.vue2.0 jsonp封装
- Tornado 支持JSONP的请求封装
- 工作中jsonp 与ajax的封装
- 自己封装的JSONP跨域函数
- 封装自己的jsonp、元素Ajax
- ajax和jsonp的原生封装
- byte[],Bitmap,YuvImage,Drawable 旋转、缩放、相互转化
- JAVA9 API翻译(Module java.activation)
- MVP+DownloadManager实现android下载功能
- 1-4 输出菱形
- 每日一点linux:lsof输出各列信息
- jsonp封装浅析
- bootstrap-选项卡头部及内容
- 吴恩达Coursera深度学习课程 DeepLearning.ai 提炼笔记(2-1)-- 深度学习的实践方面(转载)
- 初识Linux
- [SDUT](3344)数据结构实验之二叉树五:层序遍历
- 创建注册页面
- Fragment全解析系列:那些年踩过的坑以及解决方案
- Android Studio 获取开发版和发布版 SHA1 和 MD5
- 【学习笔记】工厂模式学习2