文档章节

jsonp 原理解析

dubox
 dubox
发布于 2017/05/04 12:19
字数 811
阅读 7
收藏 0

以前用jsonp 服务端都是请求别人的api 例如:百度,所以也很少注意服务端的写法。

今天用jqmobi 的 jsonP 函数请求自己的API 结果报错:SyntaxError: missing ; before statement

ee

 

但是我反复检查我的json字符串没有发现问题,十分郁闷

查了网上的一些文章 说是 要加一对()写成 “(“+data+”)”

于是加了对括弧,果然不报错了,但有一个警告:Resource interpreted as Script but transferred with MIME type text/html ;而且问题依然存在

看到script 有些不解, 不是 json吗?

于是打算去看看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

<script type="text/javascript">
       /**
        * Execute a jsonP call, allowing cross domain scripting
        * options.url - URL to call
        * options.success - Success function to call
        * options.error - Error function to call
            ```
            $.jsonP({url:"mysite.php?callback=?&foo=bar",success:function(){},error:function(){}});
            ```

        * @param {Object} options
        * @title $.jsonP(options)
        */
        $.jsonP = function(options) {
            if (isWin8) {
                options.type = "get";
                options.dataType = null;
                return $.get(options);
            }
            var callbackName = "jsonp_callback" + (++_jsonPID); //定义回调函数的 函数名(若不指定,则使用这个)
            var abortTimeout = "",
                context, callback;
            var script = document.createElement("script");  //创建请求服务器的 script对象
            var abort = function() {
                $(script).remove();
                if (window[callbackName])
                    window[callbackName] = empty;
            };
            
            /***重点***
            定义 回调函数 
            而服务器端就要输出调用这个函数的一段代码(js代码)
            即:'callbackName(data)'
            callbackName 就是url中callback的值
            data 是你想要发送到本地的数据
            *****/
            window[callbackName] = function(data) {
            
                clearTimeout(abortTimeout);
                $(script).remove();
                delete window[callbackName];
                options.success.call(context, data);    //这里执行你自己定义的 请求成功后的回调函数
            };
            
            //下面这段 是处理URL的 
            if (options.url.indexOf("callback=?") !== -1) {
                script.src = options.url.replace(/=\?/, "=" + callbackName);
            } else {

                callback = options.jsonp ? options.jsonp : "callback";                
                if (options.url.indexOf("?") === -1) {
                    options.url += ("?" + callback + "=" + callbackName);
                }
                else {
                    if(options.url.indexOf("callback=")!==-1){

                        var searcher="callback=";
                        var offset=options.url.indexOf(searcher)+searcher.length;
                        var amp=options.url.indexOf(offset);
                        if(amp===-1)
                            amp=options.url.length;
                        var oldCB=options.url.substr(offset,amp);
                        options.url=options.url.replace(searcher+oldCB,searcher+callbackName);
                        oldCB=oldCB.replace("window.","");
                        options.success=window[oldCB];
                    }
                    else {
                        options.url += ("&" + callback + "=" + callbackName);
                    }
                }
                script.src = options.url;   //将处理过的URL 作为script的src值
            }
            if (options.error) {
                script.onerror = function() {
                    clearTimeout(abortTimeout);
                    options.error.call(context, "", "error");
                };
            }
            $("head").append(script);   //将script插入到页面head中,载入成功后你在服务端输出的js代码就被执行了
            if (options.timeout > 0)
                abortTimeout = setTimeout(function() {
                    options.error.call(context, "", "timeout");
                }, options.timeout);
            return {};
        };

</script>

以上是jqmobi中jsonP函数的源码

我在其中加了一些注释 ,希望没有误导人。。。哈哈

这样就清楚了

其实是 在页面head里插入一个<script></script>,

用你的请求地址做script的 src 从而实现 异步 跨域 请求

而链接中的callback参数值将作为回调函数的名字,所以服务端这样写就可以了(php为例):

php default" style="overflow:auto;white-space:nowrap;width:590px;">

1

<!--?php echo $_GET['callback'].'('.json_encode($data).")"; ?-->

原来jsonp是这么回事儿。。。

现在再去看百度的API 发现 直接在浏览器访问API输出的是json,但当你在地址中加入callback参数时它就会输出像上面那样的js代码。。。

顿时觉得 好坑啊。。。

 

另外,上面提到的警告:Resource interpreted as Script but transferred with MIME type text/html

可以在服务端加上一句  header(‘Content-type: application/x-javascript’); 来解决,不加也不影响。。。

© 著作权归作者所有

共有 人打赏支持
dubox
粉丝 3
博文 98
码字总数 28307
作品 0
西安
程序员
私信 提问
由Java爬虫所想到的

爬虫,听起来似乎很高端,然而也就那么回事,有很多爬虫框架,Java实现的有crawler4j,WebCollector,webMagic,Python实现的最著名的应该是Scrapy,工作中用到,但是没用什么爬虫框架,整个...

开源中国刘德华
2016/06/02
100
0
Ajax+Spring MVC实现跨域请求(JSONP)

JSONP解释 在解释JSONP之前,我们需要了解下”同源策略“这个概念,这对理解跨域有帮助。基于安全的原因,浏览器是存在同源策略机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源...

熊大熊二
2015/09/18
416
2
JSONP跨域的原理解析

JavaScript是一种在Web开发中经常使用的前端动态脚本技术。在JavaScript中,有一个很重要的安全性限制,被称为“Same-Origin Policy”(同源策略)。这一策略对于JavaScript代码能够访问的页...

武文海
2016/03/21
24
0
前端与移动开发之vue-day2(3)

Vue 1.x 中 自定义元素指令【已废弃,了解即可】 使用方式: vue实例的生命周期 什么是生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期! ...

czbkzmj
2018/11/15
0
0
JQuery + JsonP 解决跨域请求

什么是跨域 跨域是指从一个域名的网页去请求另一个域名的资源。比如从www.baidu.com 页面去请求 www.google.com 的资源。跨域的严格一点的定义是:只要 协议,域名,端口有任何一个的不同,就...

刘引惟
2016/11/23
75
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周一乱弹 —— 白掌柜说了卖货不卖身

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @爱漫爱 :这是一场修行分享羽肿的单曲《Moony》 手机党少年们想听歌,请使劲儿戳(这里) @clouddyy :开不开心? 开心呀, 我又不爱睡懒觉…...

小小编辑
今天
8
0
大数据教程(11.7)hadoop2.9.1平台上仓库工具hive1.2.2搭建

上一篇文章介绍了hive2.3.4的搭建,然而这个版本已经不能稳定的支持mapreduce程序。本篇博主将分享hive1.2.2工具搭建全过程。先说明:本节就直接在上一节的hadoop环境中搭建了! 一、下载apa...

em_aaron
今天
3
0
开始看《JSP&Servlet学习笔记》

1:WEB应用简介。其中1.2.1对Web容器的工作流程写得不错 2:编写Servlet。搞清楚了Java的Web目录结构,以及Web.xml的一些配置作用。特别是讲了@WebServlet标签 3:请求与响应。更细致的讲了从...

max佩恩
今天
4
0
mysql分区功能详细介绍,以及实例

一,什么是数据库分区 前段时间写过一篇关于mysql分表的的文章,下面来说一下什么是数据库分区,以mysql为例。mysql数据库中的数据是以文件的形势存在磁盘上的,默认放在/mysql/data下面(可...

吴伟祥
今天
3
0
SQL语句查询

1.1 排序 通过order by语句,可以将查询出的结果进行排序。放置在select语句的最后。 格式: SELECT * FROM 表名 ORDER BY 排序字段ASC|DESC; ASC 升序 (默认) DESC 降序 1.查询所有商品信息,...

stars永恒
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部