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 相关文章推荐
input 输入框获得/失去焦点时隐藏/显示文字(jquery版)
Apr 02 Javascript
设置jsf的选择框h:selectOneMenu为不可编辑状态的方法
Jan 07 Javascript
JavaScript生成随机数的4种自定义函数分享
Feb 28 Javascript
JavaScript判断是否为数组的3种方法及效率比较
Apr 01 Javascript
js+html5实现canvas绘制简单矩形的方法
Jun 05 Javascript
js实现带缓冲效果的仿QQ面板折叠菜单代码
Sep 06 Javascript
JS实现完全语义化的网页选项卡效果代码
Sep 15 Javascript
javascript回到顶部特效
Jul 30 Javascript
js转换对象为xml
Feb 17 Javascript
如何使用CSS3和JQuery easing 插件制作绚丽菜单
Jun 18 jQuery
vue中解决拖拽改变存在iframe的div大小时卡顿问题
Jul 22 Javascript
js实现简单商品筛选功能
Feb 02 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
漫威DC御用漫画家去世 他的表情包曾走红网络
2020/04/09 欧美动漫
php数据库抽象层 PDO
2011/05/07 PHP
php获取淘宝分类id示例
2014/01/16 PHP
PHP函数实现分页含文本分页和数字分页
2014/10/23 PHP
THINKPHP项目开发中的日志记录实例分析
2014/12/01 PHP
在PHP程序中使用Rust扩展的方法
2015/07/03 PHP
window.location.hash 使用说明
2010/11/08 Javascript
js+xml生成级联下拉框代码
2012/07/24 Javascript
UpdatePanel和Jquery冲突的解决方法
2013/04/01 Javascript
JS与jQ读取xml文件的方法
2015/12/08 Javascript
javascript实现瀑布流加载图片原理
2016/02/02 Javascript
归纳下js面向对象的几种常见写法总结
2016/08/24 Javascript
jquery判断iPhone、Android设备类型
2016/09/14 Javascript
node.js利用redis数据库缓存数据的方法
2017/03/01 Javascript
用Vue-cli搭建的项目中引入css报错的原因分析
2017/07/20 Javascript
JS获取子、父、兄节点方法小结
2017/08/14 Javascript
10 种最常见的 Javascript 错误(频率最高)
2018/02/08 Javascript
node前端模板引擎Jade之标签的基本写法
2018/05/11 Javascript
利用Dectorator分模块存储Vuex状态的实现
2019/02/05 Javascript
详解ES7 Decorator 入门解析
2019/02/18 Javascript
python日志记录模块实例及改进
2017/02/12 Python
Python socket实现的简单通信功能示例
2018/08/21 Python
Python面向对象之类的内置attr属性示例
2018/12/14 Python
对python列表里的字典元素去重方法详解
2019/01/21 Python
opencv python 图像轮廓/检测轮廓/绘制轮廓的方法
2019/07/03 Python
Django框架视图介绍与使用详解
2019/07/18 Python
python自定义时钟类、定时任务类
2021/02/22 Python
使用OpenCV-python3实现滑动条更新图像的Canny边缘检测功能
2019/12/12 Python
Python实现CNN的多通道输入实例
2020/01/17 Python
微软开源最强Python自动化神器Playwright(不用写一行代码)
2021/01/05 Python
时尚的CSS3进度条效果
2012/02/22 HTML / CSS
使用css3实现的tab选项卡代码分享
2014/12/09 HTML / CSS
施工班组长岗位职责
2014/01/05 职场文书
学生抄作业检讨书(2篇)
2014/10/17 职场文书
施工员岗位职责
2015/02/10 职场文书
Python 中random 库的详细使用
2021/06/03 Python