JavaScript用JSONP跨域请求数据实例详解


Posted in Javascript onJanuary 06, 2017

前言

最近因为工作需要,需要把爱词霸的每日一句引入到页面上,爱词霸向外开放了 API, 接口返回 json 数据,为了让页面更轻巧,我没有用 jQuery,而是直接纯 js 写了一段代码:

<script type="text/javascript">
 function httpGetAsync(theUrl, callback)
 {
 xmlHttp = null;
 if (window.XMLHttpRequest)
 {// code for IE7, Firefox, Opera, etc.
 xmlHttp = new XMLHttpRequest();
 }
 else if (window.ActiveXObject)
 {// code for IE6, IE5
 xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
 }
 if (xmlHttp != null)
 {
 xmlHttp.onreadystatechange = function() {
 if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
 {
  callback(xmlHttp.responseText);
 }
 else
 {
  console.error("Problem retrieving XML data");
 }
 }
 xmlHttp.open("GET", theUrl, true); // true for asynchronous
 xmlHttp.setRequestHeader('Access-Control-Allow-Origin', '*');
 xmlHttp.send(null);
 }
 else
 {
 console.error("Your browser does not support XMLHTTP.");
 }
 }

 function showIcibaDS(ds_data)
 {
 // show daily sentence
 content = ds_data.content;
 note = ds_data.note;
 document.write(content + '<br>');
 document.write(note);
 }

 httpGetAsync("http://open.iciba.com/dsapi/", showIcibaDS);
</script>

运行之后数据并没有获取到,而是出现了如下错误提示:

XMLHttpRequest cannot load http://open.iciba.com/dsapi/. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 501.

这就是跨域请求的问题。那么什么是跨域请求呢?浏览器出于安全方面的考虑,采用同源策略(Same origin Policy),即只允许与同域下的接口交互。

同域是指:

  1. 同协议:如都是 http 或者 https
  2. 同域名:如都是 http://konghy.cn/a 或 http://konghy.cn/b
  3. 同端口:如都是 80 端口

也就是说,用户打开了页面: http://blog.konghy.cn, 当前页面下的 js 向 http://blog.konghy.cn/XXX 的接口发数据请求,浏览器是允许的。但假如向: http://open.iciba.com/xxx 发数据请求则会被浏览器阻止掉,因为存在跨域调用。

跨域请求的解决办法就是 JSONP(JSON with Padding) . HTML 中 script 标签可以加载其他域下的 js, JSONP 就是通过 script 标签加载数据的方式去获取数据当做 JS 代码来执行,然后再用一个回调函数抽取数据:

<script type="text/javascript">
 var cur_date = new Date();
 document.getElementById("cur_year").innerHTML = cur_date.getFullYear();

 function showIcibaDS(ds_data)
 {
 // show daily sentence
 content = ds_data.content;
 note = ds_data.note;
 ds_p = document.getElementById("iciba_ds")
 var content_span = document.createElement('span');
 var note_span = document.createElement('span');
 var br = document.createElement('br')
 content_span.innerHTML = content
 note_span.innerHTML = note
 ds_p.appendChild(content_span);
 ds_p.appendChild(br);
 ds_p.appendChild(note_span);
 }
</script>
<script type="text/javascript" src="http://open.iciba.com/dsapi/?callback=showIcibaDS"></script>

再查查资料,发现有人做了封装:

function jsonp(setting)
{
 setting.data = setting.data || {}
 setting.key = setting.key||'callback'
 setting.callback = setting.callback||function(){}
 setting.data[setting.key] = '__onGetData__'

 window.__onGetData__ = function(data) {
 setting.callback (data);
 }
 var script = document.createElement('script')
 var query = []
 for(var key in setting.data)
 {
 query.push(key + '=' + encodeURIComponent(setting.data[key])) 
 }
 script.src = setting.url + '?' + query.join('&')
 document.head.appendChild(script)
 document.head.removeChild(script)
}

jsonp({
 url: 'http://photo.sina.cn/aj/index',
 key: 'jsoncallback',
 data: { page: 1, cate: 'recommend' },
 callback: function(ret) {
 console.log(ret)
 }
})

如果你使用的是 jQuery,则可以直接用 ajax 请求数据:

<script src="js/jquery-1.11.3.js"></script>
<script>
$(function(){
 $.ajax({
 async: true,
 type: "GET",
 dataType: 'jsonp',
 jsonp: 'callback',
 jsonpCallback: 'callbackfunction',
 url: "http://open.iciba.com/dsapi/",
 data: "",
 timeout: 3000,
 contentType: "application/json;utf-8",
 success: function(data) {
 console.log(data);
 }
 });
})
</script>

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

参考资料

https://3water.com/article/75669.htm

https://zhuanlan.zhihu.com/p/22600501

Javascript 相关文章推荐
关于使用runtimeStyle属性问题讨论文章
Mar 08 Javascript
javascript奇异的arguments分析
Oct 20 Javascript
JQuery优缺点分析说明
Apr 10 Javascript
给页面渲染时间加速 干掉Dom Level 0 Event
Dec 19 Javascript
多个datatable共存造成多个表格的checkbox都被选中
Jul 11 Javascript
JavaScript获取路径设计源码
May 22 Javascript
JavaScript解析json格式数据简单示例
Dec 09 Javascript
JavaScript实现广告弹窗效果
Aug 09 Javascript
老生常谈的跨域处理
Jan 11 Javascript
vue如何引用其他组件(css和js)
Apr 13 Javascript
微信小程序自定义导航栏实例代码
Apr 05 Javascript
VUE.js实现动态设置输入框disabled属性
Oct 28 Javascript
js实现前端分页页码管理
Jan 06 #Javascript
纯js实现倒计时功能
Jan 06 #Javascript
JS正则截取两个字符串之间及字符串前后内容的方法
Jan 06 #Javascript
微信小程序开发教程-手势解锁实例
Jan 06 #Javascript
jQuery ajax的功能实现方法详解
Jan 06 #Javascript
详解JS中定时器setInterval和setTImeout的this指向问题
Jan 06 #Javascript
Jqprint实现页面打印
Jan 06 #Javascript
You might like
php中$_REQUEST、$_POST、$_GET的区别和联系小结
2011/11/23 PHP
详解PHP中mb_strpos的使用
2018/02/04 PHP
Mac系统下安装PHP Xdebug
2018/03/30 PHP
jquery插件hiAlert实现网页对话框美化
2015/05/03 Javascript
Kindeditor在线文本编辑器如何过滤HTML
2016/04/14 Javascript
js图片轮播手动切换特效
2017/01/12 Javascript
js Dom实现换肤效果
2017/10/21 Javascript
vue.js中引入vuex储存接口数据及调用的详细流程
2017/12/14 Javascript
jQuery进阶实践之利用最优雅的方式如何写ajax请求
2017/12/20 jQuery
JavaScript实现重力下落与弹性效果的方法分析
2017/12/20 Javascript
Vue的elementUI实现自定义主题方法
2018/02/23 Javascript
一百行JS代码实现一个校验工具
2019/04/30 Javascript
微信小程序实现弹框效果
2020/05/26 Javascript
Python创建二维数组实例(关于list的一个小坑)
2017/11/07 Python
Python hexstring-list-str之间的转换方法
2019/06/12 Python
PyQt5 多窗口连接实例
2019/06/19 Python
python实现拼图小游戏
2020/02/22 Python
python argparse传入布尔参数false不生效的解决
2020/04/20 Python
django 外键创建注意事项说明
2020/05/20 Python
python利用faker库批量生成测试数据
2020/10/15 Python
Django-celery-beat动态添加周期性任务实现过程解析
2020/11/26 Python
ECHT官方网站:男女健身服
2020/02/14 全球购物
Strathberry苏贝瑞中国官网:西班牙高级工匠手工打造
2020/10/19 全球购物
哪些情况下不应该使用索引
2015/07/20 面试题
大学生村官典型材料
2014/01/12 职场文书
小松树教学反思
2014/02/11 职场文书
法制宣传标语
2014/06/23 职场文书
学校法制宣传月活动总结
2014/07/03 职场文书
预备党员思想汇报1000字
2014/10/07 职场文书
秋季运动会开幕词
2015/01/28 职场文书
捐书活动倡议书
2015/04/27 职场文书
公司食堂管理制度
2015/08/05 职场文书
Python爬虫之爬取最新更新的小说网站
2021/05/06 Python
Java比较两个对象中全部属性值是否相等的方法
2021/08/07 Java/Android
python微信智能AI机器人实现多种支付方式
2022/04/12 Python
在MySQL中你成功的避开了所有索引
2022/04/20 MySQL