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 相关文章推荐
Jquery和JS用外部变量获取Ajax返回的参数值的方法实例(超简单)
Jun 17 Javascript
jquery队列函数用法实例
Dec 16 Javascript
原生js实现类似弹窗抖动效果
Apr 02 Javascript
JS模式之单例模式基本用法
Jun 30 Javascript
使用vue.js开发时一些注意事项
Apr 27 Javascript
JavaScript“尽快失败”的原则实例详解
Oct 08 Javascript
微信小程序 利用css实现遮罩效果实例详解
Jan 21 Javascript
详解webpack2异步加载套路
Sep 14 Javascript
javascript防抖函数debounce详解
Jun 11 Javascript
node.js实现上传文件功能
Jul 15 Javascript
详解vue页面首次加载缓慢原因及解决方案
Nov 06 Javascript
Element的el-tree控件后台数据结构的生成以及方法的抽取
Mar 05 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扩展介绍与开发教程
2010/08/19 PHP
基于PHP生成静态页的实现方法
2013/05/10 PHP
PHP 获取文件权限函数介绍
2013/07/11 PHP
php读取纯真ip数据库使用示例
2014/01/26 PHP
详解WordPress中创建和添加过滤器的相关PHP函数
2015/12/29 PHP
Laravel中Trait的用法实例详解
2016/03/16 PHP
JS循环遍历JSON数据的方法
2014/07/08 Javascript
JQuery zClip插件实现复制页面内容到剪贴板
2015/11/02 Javascript
概述VUE2.0不可忽视的很多变化
2016/09/25 Javascript
详解EasyUi控件中的Datagrid
2017/08/23 Javascript
vue中component组件的props使用详解
2017/09/04 Javascript
VUEJS 2.0 子组件访问/调用父组件的实例
2018/02/10 Javascript
vue的传参方式汇总和router使用技巧
2018/05/22 Javascript
vue通过点击事件读取音频文件的方法
2018/05/30 Javascript
Javascript 实现 Excel 导入生成图表功能
2018/10/22 Javascript
JS实现水平遍历和嵌套递归操作示例
2019/08/15 Javascript
Vue 一键清空表单的实现方法
2020/02/07 Javascript
Python模块学习 re 正则表达式
2011/05/19 Python
python实现的文件夹清理程序分享
2014/11/22 Python
Python实现批量下载图片的方法
2015/07/08 Python
使用Python的Django和layim实现即时通讯的方法
2018/05/25 Python
Python 200行代码实现一个滑动验证码过程详解
2019/07/11 Python
python之pexpect实现自动交互的例子
2019/07/25 Python
安装pyecharts1.8.0版本后导入pyecharts模块绘图时报错: “所有图表类型将在 v1.9.0 版本开始强制使用 ChartItem 进行数据项配置 ”的解决方法
2020/08/18 Python
html5 sessionStorage会话存储_动力节点Java学院整理
2017/07/06 HTML / CSS
MCM英国官网:奢侈皮具制品
2017/04/18 全球购物
采购部岗位职责
2013/11/24 职场文书
企业安全生产演讲稿
2014/05/09 职场文书
2014幼儿园班主任工作总结
2014/12/04 职场文书
2015年度个人思想工作总结
2015/04/08 职场文书
幼儿园小班工作总结2015
2015/04/25 职场文书
餐饮服务食品安全承诺书
2015/04/29 职场文书
党员进社区活动总结
2015/05/07 职场文书
大学团日活动总结书
2015/05/11 职场文书
读书笔记怎么写
2015/07/01 职场文书
Go Grpc Gateway兼容HTTP协议文档自动生成网关
2022/06/16 Golang