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下阻止表单重复提交、防刷新、防后退
Aug 17 Javascript
动态载入/删除/更新外部 JavaScript/Css 文件的代码
Jul 03 Javascript
jQuery powerFloat万能浮动层下拉层插件使用介绍
Dec 27 Javascript
JQuery插件Quicksand实现超炫的动画洗牌效果
May 03 Javascript
JS实现图片剪裁并预览效果
Aug 12 Javascript
js面向对象编程总结
Feb 16 Javascript
详解小程序循环require之坑
Mar 08 Javascript
小程序中英文混合排序问题解决
Aug 02 Javascript
解决layui中onchange失效以及form动态渲染失效的问题
Sep 27 Javascript
基于Vue sessionStorage实现保留搜索框搜索内容
Jun 01 Javascript
使用element-ui +Vue 解决 table 里包含表单验证的问题
Jul 17 Javascript
JavaScript实现登录窗体
Jun 22 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函数spl_autoload_register()用法和__autoload()介绍
2012/02/04 PHP
让ThinkPHP支持大小写url地址访问的方法
2014/10/31 PHP
PHP 实现判断用户是否手机访问
2015/01/21 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
PHP实现创建一个RPC服务操作示例
2020/02/23 PHP
js option删除代码集合
2008/11/12 Javascript
js 判断checkbox是否选中的实现代码
2010/11/23 Javascript
jquery实现可拖动DIV自定义保存到数据的实例
2013/11/20 Javascript
JavaScript原生对象之Number对象的属性和方法详解
2015/03/13 Javascript
利用require.js与angular搭建spa应用的方法实例
2017/07/19 Javascript
详解webpack提取第三方库的正确姿势
2017/12/22 Javascript
Vue.js 实现微信公众号菜单编辑器功能(二)
2018/05/08 Javascript
vuejs router history 配置到iis的方法
2018/09/20 Javascript
微信小程序制作扭蛋机代码实例
2019/09/24 Javascript
js实现坦克大战游戏
2020/02/24 Javascript
[04:47]DOTA2-潍坊风行电子俱乐部探秘
2014/08/08 DOTA
python为tornado添加recaptcha验证码功能
2014/02/26 Python
Python监控主机是否存活并以邮件报警
2015/09/22 Python
Python中对象的引用与复制代码示例
2017/12/04 Python
python 消除 futureWarning问题的解决
2019/12/25 Python
基于python爬取有道翻译过程图解
2020/03/31 Python
sklearn的predict_proba使用说明
2020/06/28 Python
如何一键升级Python所有包
2020/11/05 Python
Python使用windows设置定时执行脚本
2020/11/12 Python
Python应用自动化部署工具Fabric原理及使用解析
2020/11/30 Python
python unichr函数知识点总结
2020/12/16 Python
德国自然时尚和有机产品购物网站:Waschbär
2019/05/29 全球购物
会计专业毕业生自我评价
2013/09/25 职场文书
便利店投资创业计划书
2014/02/08 职场文书
党员党性分析材料
2014/02/17 职场文书
电子商务专业求职信
2014/03/08 职场文书
管理学院毕业生自荐信范文
2014/03/10 职场文书
高中生班主任评语
2014/04/25 职场文书
大学专科自荐信
2014/06/17 职场文书
学校领导班子四风对照检查材料
2014/09/27 职场文书
如何签定毕业生就业协议书
2014/09/28 职场文书