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 相关文章推荐
游戏人文件夹程序 ver 3.0
Jul 14 Javascript
再次分享18个非常棒的jQuery表格插件
Apr 10 Javascript
利用JavaScript的AngularJS库制作电子名片的方法
Jun 18 Javascript
javascript封装的sqlite操作类实例
Jul 17 Javascript
JS组件Bootstrap实现弹出框和提示框效果代码
Dec 08 Javascript
详解JavaScript正则表达式之RegExp对象
Dec 13 Javascript
JS实现的数组去除重复数据算法小结
Nov 17 Javascript
Vue实现简易翻页效果源码分享
Nov 08 Javascript
微信小程序学习笔记之文件上传、下载操作图文详解
Mar 29 Javascript
Vue图片浏览组件v-viewer用法分析【支持旋转、缩放、翻转等操作】
Nov 04 Javascript
浅谈vuex的基本用法和mapaction传值问题
Nov 08 Javascript
小程序实现长按保存图片的方法
Dec 31 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
Yii2实现上下联动下拉框功能的方法
2016/08/10 PHP
PHP中empty,isset,is_null用法和区别
2017/02/19 PHP
详解提高使用Java反射的效率方法
2019/04/29 PHP
关于php开启错误提示的总结
2019/09/24 PHP
JS 面向对象之神奇的prototype
2011/02/26 Javascript
事件绑定之小测试  onclick &amp;&amp; addEventListener
2011/07/31 Javascript
jquery parent和parents的区别分析
2013/10/02 Javascript
JQuery的$和其它JS发生冲突的快速解决方法
2014/01/24 Javascript
原生Ajax 和jQuery Ajax的区别示例分析
2014/12/17 Javascript
AngularJS基础学习笔记之表达式
2015/05/10 Javascript
javascript框架设计之种子模块
2015/06/23 Javascript
深入理解JavaScript中的对象复制(Object Clone)
2016/05/18 Javascript
javascript实现的上下无缝滚动效果
2016/09/19 Javascript
简单的js表格操作
2016/09/24 Javascript
JavaScript寄生组合式继承实例详解
2018/01/06 Javascript
js实现同一个页面,多个enter事件绑定的示例
2018/10/10 Javascript
20道JS原理题助你面试一臂之力(必看)
2019/07/22 Javascript
jQuery实现的图片点击放大缩小功能案例
2020/01/02 jQuery
[02:57]DOTA2亚洲邀请赛小组赛第四日 赛事回顾
2015/02/02 DOTA
[51:32]Optic vs Serenity 2018国际邀请赛淘汰赛BO3 第一场 8.22
2018/08/23 DOTA
Python3 正在毁灭 Python的原因分析
2014/11/28 Python
Python中利用原始套接字进行网络编程的示例
2015/05/04 Python
Python实现快速多线程ping的方法
2015/07/15 Python
Python操作json的方法实例分析
2018/12/06 Python
Python将字符串常量转化为变量方法总结
2019/03/17 Python
Pytorch中实现只导入部分模型参数的方式
2020/01/02 Python
Python hashlib和hmac模块使用方法解析
2020/12/08 Python
python opencv图像处理(素描、怀旧、光照、流年、滤镜 原理及实现)
2020/12/10 Python
中国最大的团购网站:聚划算
2016/09/21 全球购物
玛蒂尔达简服装:Matilda Jane Clothing
2019/02/13 全球购物
环保项目建议书
2014/08/26 职场文书
客房部经理岗位职责
2015/02/02 职场文书
《我要的是葫芦》教学反思
2016/02/18 职场文书
python 利用 PIL 将数组值转成图片的实现
2021/04/12 Python
python 实现德洛内三角剖分的操作
2021/04/22 Python
SpringBoot+VUE实现数据表格的实战
2021/08/02 Java/Android