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 相关文章推荐
拖动table标题实现改变td的大小(css+js代码)
Apr 16 Javascript
js实现简单的星级选择器提交效果适用于评论等
Oct 18 Javascript
Javascript:为input设置readOnly属性(示例讲解)
Dec 25 Javascript
ListBox实现上移,下移,左移,右移的简单实例
Feb 13 Javascript
Node连接mysql数据库方法介绍
Feb 07 Javascript
使用get方式提交表单在地址栏里面不显示提交信息
Feb 21 Javascript
在Vue组件中使用 TypeScript的方法
Feb 28 Javascript
微信小程序实现bindtap等事件传参
Apr 08 Javascript
vue cli安装使用less的教程详解
Jul 12 Javascript
Layui数据表格 前后端json数据接收的方法
Sep 19 Javascript
vue 验证码界面实现点击后标灰并设置div按钮不可点击状态
Oct 28 Javascript
ant design vue中日期选择框混合时间选择器的用法说明
Oct 27 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
模拟OICQ的实现思路和核心程序(三)
2006/10/09 PHP
PHP 选项及相关信息函数库
2006/12/04 PHP
用php实现的获取网页中的图片并保存到本地的代码
2010/01/05 PHP
thinkphp3.0 模板中函数的使用
2012/11/13 PHP
深入理解:XML与对象的序列化与反序列化
2013/06/08 PHP
浅析php fwrite写入txt文件的时候用 \r\n不能换行的问题
2013/08/06 PHP
避免Smarty与CSS语法冲突的方法
2015/03/02 PHP
php 截取中英文混合字符串的方法
2018/05/31 PHP
tp5.1 框架数据库常见操作详解【添加、删除、更新、查询】
2020/05/26 PHP
javascript中用星号表示预录入内容的实现代码
2011/01/08 Javascript
拖动table标题实现改变td的大小(css+js代码)
2013/04/16 Javascript
JS 屏蔽键盘不可用与鼠标右键不可用的方法
2013/11/18 Javascript
javascript实现点击按钮让DIV层弹性移动的方法
2015/02/24 Javascript
jQuery实现类似标签风格的导航菜单效果代码
2015/08/25 Javascript
javascript每日必学之循环
2016/02/19 Javascript
原生js实现class的添加和删除简单代码
2016/07/12 Javascript
jQuery实现根据滚动条位置加载相应内容功能
2016/07/18 Javascript
JS面试题---关于算法台阶的问题
2016/07/26 Javascript
实现JavaScript高性能的数据存储
2016/12/11 Javascript
从零开始学习Node.js系列教程之SQLite3和MongoDB用法分析
2017/04/13 Javascript
详解vue.js的事件处理器v-on:click
2017/06/27 Javascript
BootStrap Table前台和后台分页对JSON格式的要求
2017/06/28 Javascript
Vue中使用sass实现换肤功能
2018/09/07 Javascript
axios解决高并发的方法:axios.all()与axios.spread()的操作
2020/11/09 Javascript
[11:27]《一刀刀一天》之DOTA全时刻20:TI4总奖金突破920W TS赛事分析
2014/06/18 DOTA
Python入门篇之对象类型
2014/10/17 Python
flask框架中勾子函数的使用详解
2018/08/01 Python
python 机器学习之支持向量机非线性回归SVR模型
2019/06/26 Python
英国领先的高街书籍专家:Waterstones
2018/02/01 全球购物
学生会离职感言
2014/02/11 职场文书
微电影大赛策划方案
2014/06/05 职场文书
股指期货心得体会
2014/09/13 职场文书
2014预备党员批评与自我批评思想汇报
2014/09/20 职场文书
护士2014年终工作总结
2014/11/11 职场文书
军训个人总结
2015/03/03 职场文书
2019消防宣传标语!
2019/07/10 职场文书