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 相关文章推荐
javascript网页关键字高亮代码
Jul 30 Javascript
javascript 混合的构造函数和原型方式,动态原型方式
Dec 07 Javascript
JS Excel读取和写入操作(模板操作)实现代码
Apr 11 Javascript
Safari5中alert的无限循环BUG
Apr 07 Javascript
JScript分割字符串示例代码
Sep 04 Javascript
谈谈jQuery Ajax用法详解
Nov 27 Javascript
Javascript 实现全屏滚动实例代码
Dec 31 Javascript
如何使用angularJs
May 08 Javascript
JS实现的简单折叠展开动画效果示例
Apr 28 Javascript
解决angular双向绑定无效果,ng-model不能正常显示的问题
Oct 02 Javascript
从vue源码看props的用法
Jan 09 Javascript
vuex页面刷新导致数据丢失的解决方案
Dec 10 Vue.js
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学习 变量使用总结
2011/03/24 PHP
模板引擎正则表达式调试小技巧
2011/07/20 PHP
php使用PDO操作MySQL数据库实例
2014/12/30 PHP
在WordPress中使用wp_count_posts函数来统计文章数量
2016/01/05 PHP
PHP 中常量的知识整理
2017/04/14 PHP
php微信开发之关注事件
2018/06/14 PHP
php根据命令行参数生成配置文件详解
2019/03/15 PHP
PHP之多条件混合筛选功能的实现方法
2019/10/09 PHP
web 页面分页打印的实现
2009/06/22 Javascript
js网页实时倒计时精确到秒级
2014/02/10 Javascript
JavaScript中对象property的删除方法介绍
2014/12/30 Javascript
Javascript中的getUTCDay()方法使用详解
2015/06/10 Javascript
Vue.js 递归组件实现树形菜单(实例分享)
2016/12/21 Javascript
vue实现列表的添加点击
2016/12/29 Javascript
js编写选项卡效果
2017/05/23 Javascript
vue-router的使用方法及含参数的配置方法
2018/11/13 Javascript
如何解决.vue文件url引用文件的问题
2019/01/18 Javascript
详解vue.js移动端配置flexible.js及注意事项
2019/04/10 Javascript
JS异步宏队列微队列原理详解
2020/09/09 Javascript
js实现购物车商品数量加减
2020/09/21 Javascript
WebPack工具运行原理及入门教程
2020/12/02 Javascript
[01:09]模型精美,特效酷炫!TI9不朽宝藏Ⅰ鉴赏
2019/05/10 DOTA
python版opencv摄像头人脸实时检测方法
2018/08/03 Python
python判断数字是否是超级素数幂
2018/09/27 Python
5款Python程序员高频使用开发工具推荐
2019/04/10 Python
详解PyCharm安装MicroPython插件的教程
2019/06/24 Python
Pytorch提取模型特征向量保存至csv的例子
2020/01/03 Python
python实现音乐播放和下载小程序功能
2020/04/26 Python
python 第三方库paramiko的常用方式
2021/02/20 Python
老生常谈CSS中的长度单位
2016/06/27 HTML / CSS
日本AOKI官方商城:AOKI西装
2020/06/11 全球购物
百度JavaScript笔试题
2015/01/15 面试题
寻找最美家庭活动方案
2014/08/20 职场文书
2016教师学习党章心得体会
2016/01/15 职场文书
员工给公司的建议书
2019/06/24 职场文书
Mysql数据库中datetime、bigint、timestamp来表示时间选择,谁来存储时间效率最高
2021/08/23 MySQL