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:以前写的xmlhttp池,代码
May 18 Javascript
jQuery 表格工具集
Apr 25 Javascript
GRID拖拽行的实例代码
Jul 18 Javascript
JavaScript实现自动对页面上敏感词进行屏蔽的方法
Jul 27 Javascript
seajs学习教程之基础篇
Oct 20 Javascript
实例浅析js的this
Dec 11 Javascript
vue调用高德地图实例代码
Apr 28 Javascript
移动端网页开发调试神器Eruda的介绍与使用技巧
Oct 30 Javascript
浅谈vue首屏加载优化
Jun 28 Javascript
浅谈如何优雅处理JavaScript异步错误
Nov 12 Javascript
vue中使用WX-JSSDK的两种方法(推荐)
Jan 18 Javascript
extjs图形绘制之饼图实现方法分析
Mar 06 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 生成饼图 三维饼图
2009/09/28 PHP
ThinkPHP查询返回简单字段数组的方法
2014/08/25 PHP
php实现的替换敏感字符串类实例
2014/09/22 PHP
php常用字符串处理函数实例分析
2014/11/22 PHP
php判断当前用户已在别处登录的方法
2015/01/06 PHP
php使用指定字符列表生成随机字符串的方法
2015/04/18 PHP
WordPress中用于获取搜索表单的PHP函数使用解析
2016/01/05 PHP
thinkphp3.2.0 setInc方法 源码全面解析
2018/01/29 PHP
Ajax请求PHP后台接口返回信息的实例代码
2018/08/21 PHP
popdiv
2006/07/14 Javascript
innerHTML与jquery里的html()区别介绍
2012/10/12 Javascript
JavaScript中的运算符种类及其规则介绍
2013/09/26 Javascript
超链接的禁用属性Disabled使用示例
2014/07/31 Javascript
AngularJS中实现显示或隐藏动画效果的方式总结
2015/12/31 Javascript
js中string和number类型互转换技巧(分享)
2016/11/28 Javascript
jQuery中弹出iframe内嵌页面元素到父页面并全屏化的实例代码
2016/12/27 Javascript
jQuery插件zTree实现删除树节点的方法示例
2017/03/08 Javascript
JS实现的抛物线运动效果示例
2018/01/30 Javascript
基于three.js实现的3D粒子动效实例代码
2019/04/09 Javascript
小程序简单两栏瀑布流效果的实现
2019/12/18 Javascript
微信小程序封装多张图片上传api代码实例
2019/12/30 Javascript
修改Vue打包后的默认文件名操作
2020/08/12 Javascript
[49:12]完美世界DOTA2联赛PWL S2 Magma vs GXR 第二场 11.29
2020/12/02 DOTA
Python中字符串的修改及传参详解
2016/11/30 Python
python使用Matplotlib绘制分段函数
2018/09/25 Python
Selenium 安装和简单使用的实现
2020/12/04 Python
Python绘制数码晶体管日期
2021/02/19 Python
电气工程及其自动化自我评价四篇
2013/09/24 职场文书
办公室前台的岗位职责
2013/12/20 职场文书
学习考察心得体会
2014/09/04 职场文书
个人四风问题对照检查材料
2014/10/01 职场文书
成绩单评语
2015/01/04 职场文书
2015年感恩节活动总结
2015/03/24 职场文书
导游词之徐州-云龙山
2019/09/29 职场文书
MySQL之高可用集群部署及故障切换实现
2021/04/22 MySQL
简单且有用的Python数据分析和机器学习代码
2021/07/02 Python