写在前面:最近在回顾ajax请求时,对跨域数据请求产生了极大的兴趣,奈何刚开始自己天真的以为jsonp无敌到可以跨域拿到任何开放接口的数据,于是开启了自己的踩坑之路。最先是顺利的用jsonp拿到了淘宝的搜索框提示,以为“就这”。谁曾想痛苦来的那么突然,接着在请求一些网上免费接口时便陷入深渊,那么来分享一下我的爬坑之路。
入坑
1. 用jsonp请求淘宝搜索框提示
- 原提示框:
- 打开开发者工具,找到搜索接口,自己用jsonp请求此接口:
示例代码:
$.ajax({
// 请求地址
url: 'https://suggest.taobao.com/sug',
// jquery的jsonp请求必带参数
dataType: 'jsonp',
// 根据原请求地址写入参数
data: {
code: 'utf-8',
q: '键盘',
extras: '键盘',
area: 'c2c',
bucketid: 'atb_search',
unid: '',
clk1: '',
pid: 'mm_50570328_39070332_145428725',
},
// 请求成功时返回数据
success: function(data) {
console.log(data)
}
})
注意:对于jsonp请求的了解可查看此小姐姐的文章,很详细,自己也有学到(https://blog.csdn.net/m0_38134431/article/details/84393158)
- 发送请求拿到数据:
总结:jsonp的原理大家看完文章一定已经很清楚了,那么它请求数据的原理为函数的调用,如上图。
翻车
2. 开始用一些网上的免费接口
- 写请求代码:
$.ajax({
url: 'http://api.avatardata.cn/ShengXiaoPeiDui/Lookup',
dataType: 'jsonp',
data: {
key: '1028fe71be664298a07485e8e460557a',
shengxiao1: '虎',
shengxiao2: '兔'
},
success: function(data) {
console.log(JSON.parse(data))
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log(XMLHttpRequest.status);
console.log(XMLHttpRequest.readyState);
console.log(textStatus);
}
})
- 请求的响应结果:
- 自救过程:
- 我以为是jquery封装的jsonp严格模式的原因,就用了自己封装的jsonp,可结局一样。
- 我惊奇的发现,虽然没有打印请求数据,但结果竟然可手动访问,我这“改变世界的冲动就上来了”,一顿操作,没得啥用。
- 我看到报的警告,用我这中国式英语,也算翻译了一通(跨源读取阻塞(CORB)阻塞的跨源响应“”使用MIME类型application/json。)
- 起初的我还不以为然,没有加error函数,结果“头都碰烂了”(各种百度,各种查),以为Google晃我。接着加上error函数,又是一顿查,报错就离谱,哈哈哈。兜兜转转一天就这样过去了哈。
- 最后才开始注意打印的“parsererror”,是:文本分析器错误,简单点:请求方式与返回数据格式冲突,奈何都到这一步了,本人还是认为jsonp无敌,哈哈哈。
爬坑
意识到问题着手解决
1. 开始各种搜
- 开始了解“parsererror”相关的文章,看看有没有同学跟我一样,结果发现还是自己最菜(哈哈哈)。
- 开始对json、jsonp的数据格式进行了解,还是这位小姐姐的文章让我发现了自己请求的问题,相关文章(https://blog.csdn.net/m0_38134431/article/details/83787452)
- 奈何还是无果,因为我坚信jsonp跨域无敌(啪啪打脸)。
- 最后没能忍住对知识的渴望,还是请教了这位小姐姐,人家非常耐心的回复了我,人真的超好。
2. 成功脱坑
- 最终知道了jsonp不是无敌的。
- 因为自己请求的那个接口支持数据类型为json/xml,不支持函数的调用。
- 因为自己最初接触jsonp时,要么是访问本地服务器,要么是老师讲的就是一些支持jsonp请求的接口。让自己误以为jsonp辣么强(跨域无限制)。
- jsonp请求要想成功,必须有服务器端返回的函数调用,函数的参数作为数据.
- 数据接口大多支持json、xml格式;切记不是所有的接口都支持jsonp请求,毕竟jsonp请求只支持get方式,安全方面有待考量。
拓展
接着再对那个接口进行请求
那么问题来了,服务器不支持jsonp请求,如何拿到数据。此处用到了访问非同源数据,自身服务器的解决方案
了解更多同源政策,可看在下的另一篇文章(https://blog.csdn.net/cwq521o/article/details/106000280)
此处请求的原理为:服务器端不受同源政策的限制:配置本地服务器访问远程接口(拿到请求数据),再有客户端访问本地服务器(拿到数据)
1. 配置本地服务器
// 引入express框架
const express = require('express');
// 引入核心模块path(路径)
const path = require('path');
// 引入请求服务器模块request
const request = require('request');
// 声明服务器
const app = express();
// 访问静态资源
app.use(express.static(path.join(__dirname, 'public')));
// 建立本地请求路由
app.get('/serice', (req, res) => {
request(' http://api.avatardata.cn/ShengXiaoPeiDui/Lookup?key=1028fe71be664298a07485e8e460557a&shengxiao1=' + encodeURI(req.query.shengxiao1) + '&shengxiao2=' + encodeURI(req.query.shengxiao2) + '', (err, respones, body) => {
res.send(body);
})
// res.send('ok')
})
// 监听端口
app.listen(3000, () => {
console.log('服务器启动成功,端口3000')
})
2. 写请求代码(ajax请求)
<input type="text" name="" id="shengxiao1">
<input type="text" name="" id="shengxiao2">
<button>发送</button>
<script>
$("button").on('click', function() {
$.ajax({
type: 'get',
url: 'http://localhost:3000/serice',
data: {
shengxiao1: $("#shengxiao1").val(),
shengxiao2: $("#shengxiao2").val(),
},
success: function(data) {
console.log(data)
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log(XMLHttpRequest.status);
console.log(XMLHttpRequest.readyState);
console.log(textStatus);
}
})
})
</script>
注意:ajax请求,支持get,post以及RESTful风格的API,此处用get请求
3. 客户端发送请求
最后,成功通过跨域拿到此接口数据。长舒一口气,害。
数据格式,告诉我了一切,哈哈哈。
最后
写在最后:希望自己今后所学要多进行扩展性的实践,“多给自己找茬”,学习要有深度,再有广度。对基础知识定期回顾,以免再酿成今天的事故。还是非常感谢帮助到自己的博主们(点名表扬神秘小姐姐),我们一起加油,Come on