Ajax编程
回顾
-
JS数据 -> JSON字符串
- JSON.stringify()
-
JSON字符串 -> JS数据
- JSON.parse()
-
JSON文件里必须用双引号, 格式要求严谨
-
XHR2新增功能
- timeout - 超时时间设置
- ontimeout - 超时的事件 (而且自动停止这次请求)
-
使用onload替代onreadystatechange
-
前台往后台传递数据的方式
- GET方式: 通过url后面?key=value&key=value格式字符串
- POST方式
- body体里: key=value&key=value 格式的字符串
- body体里: 表单二进制流 前端用FormData() 来装载
什么方式, 什么内容类型, 参数名, 都要和后台对上
-
上传文件
- 通过FormData装载然后传递给后台的api接口
11. 跨域介绍
11.0 什么是跨域?
Ajax所在页面的协议,域名和端口, 与要请求的URL的协议, 域名, 端口有一个不一致的就产生跨域
- 跨域报错提示: (记住开头3个单词)
// Ajax所在html页面的 协议/域名/端口号 和
// Ajax要请求的url的 协议/域名/端口号 对不上就发生跨域访问
// 例如:
// 当前Ajax所在html页面(假设用live server插件打开) - http://127.0.0.1:5500
// Ajax要请求的url地址 - http://网页新闻/
// 这就发生了跨域
$.ajax({
url: "http://c.m.163.com/nc/article/headline/T1348647853363/0-40.html",
type: "GET",
success (res) {
console.log(res);
}
})
// 总结: 运行后报错
// Access to XMLHttpRequest at 'http://c.m.163.com/nc/article/headline/T1348647853363/0-40.html' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
// Access to XMLHttpRequest - 连接访问XMLHttpRequest
// at xxx from origin yyy - 从yyy地址到xxx地址
// has been blocked by CORS policy: - 已被CORS策略阻止
// No 'Access-Control-Allow-Origin' header is present on the requested resource - 请求的资源上不存在“Access Control Allow Origin”标头
同源策略
-
同源:
- Ajax所在页面的协议,域名和端口, 与要请求的URL的协议, 域名, 端口全都一样就是同源
-
跨域:不同源就是跨域
- Ajax所在页面的协议,域名和端口, 与要请求的URL的协议, 域名, 端口有一个不一致的就产生跨域
它是浏览器提供的一种安全机制,限制来自不同源的数据。现代浏览器会先判断服务器是否允许跨域, 如果不允许则报错 (后端不支持跨域请求)
11.1 跨域解决方案 - jsonp
我们希望:浏览器可以通过Ajax跨域得到数据
-
jsonp (需要前端和后端的配合才可以)- 不常用
- 除了Ajax能发送请求, script标签也能请求一个URL地址来拿到东西吧?
<!-- 1. (必须理解): script的src引入的文件, 其实就是把文件里所有的内容, 都下载引入进来, 放到script里当做js代码执行了 -->
<!-- <script src="./11.1.txt"></script> -->
<!-- 2. 那我这个地址里返回一串JS函数调用的代码呢? -->
<!-- src引入的代码是 callbackFn(数组) - 是不是在调用这个页面callbackFn函数执行呢? -->
<script>
function callbackFn(arr) {
// 函数被下面src引入地址的代码执行了
console.log(arr);
}
</script>
<script src="./11.2"></script>
<!-- 3. jsonp使用 -->
<!-- jsonp只是个概念, 和JSON没关系, 这里请求后台的接口, 后台接口会返回你传给后台的方法名(后台的数据) 回来, 嵌入到script执行, 调用你定义好的myFn执行并且把值传入 -->
<script>
function myFn(arr) {
console.log(arr);
}
</script>
<script src="http://123.57.109.30:3006/api/jsonp?callback=myFn"></script>
<!-- 还可以优化一下写法(了解-无需写-因为jQ内部这端代码已经帮助我们封装了) -->
<script type="text/javascript">
function nihao(data) {
console.log(data)
}
// 动态创建script发送的请求就是异步的
// 动态创建一个script标签,通过他的src属性发送请求,然后把标签添加页码中,然后定义回调函数
var script = document.createElement('script')
script.src = 'http://123.57.109.30:3006/api/jsonp?callback=nihao&uname=lisi&age=12'
// 把动态创建的script标签追加到head标签里面
var head = document.getElementsByTagName('head')[0]
head.appendChild(script)
// 请求发送完成后再把刚刚创建的标签删除了
head.removeChild(script)
</script>
- 所以后端给了我一个地址, 让我传递一个方法名过去
- 后端通过这个方法名(), 把值放入进去, 形成一个字符串, 返回到script标签地方加载, 执行了当前页面的函数并传值
11.2 jQ - 对jsonp的支持
- $.ajax() 该方法可以发送jsonp请求,jsonp请求本质上不是Ajax
<script>
$.ajax({
// 请求地址
url: 'http://123.57.109.30:3006/api/jsonp',
// 服务端返回的数据格式:json(默认)/text/jsonp
dataType: 'jsonp',
// 回调函数
success: function (data) {
console.log(data)
}
})
</script>
- 所以Ajax创建了一次script的src请求, 内部自己带上了callback的key名字, 以及自己内部生成的方法名jQuery35107700325141788553_1606362547035
- _ 对应的值是一个时间戳 (防止浏览器缓存)
假如后台的jsonp的参数名, 不叫callback怎么办?, 叫cb, 那么用jQ默认的就不行了
<script>
$.ajax({
// 请求地址
url: 'http://123.57.109.30:3006/api/jsonp2',
// 服务端返回的数据格式:json(默认)/text/jsonp
dataType: 'jsonp',
jsonp: "cb",
// 回调函数
success: function (data) {
console.log(data)
}
})
</script>
jsonp的缺点
- 仅支持get请求,不支持其他请求方式
- script标签发出请求本身就是get,不支持别的请求方式
- get请求传递的数据量有限制(URL地址的长度不超过8000个字符)
- post请求可以传递更多数据(post用请求体方式传递)
- 如果确实希望跨域post提交数据,怎么办?让后端去做CORS
11.3 跨域解决方案 - cors
- cors(纯粹的后端技术)- 前端啥也不用干直接请求 - 常用
- 如果后端实现了cors配置,那么前端就可以直接跨域获取对应的数据
// 只需要后端开启 - 演示下即可
// 允许跨域资源共享 - nodejs 后端代码 - 前端不用写
const cors = require('cors')
app.use(cors())
- 前端正常请求即可
// 现代浏览器默认已经支持跨域访问了, 再Ajax请求url前, 浏览器会先去后端请求一次, 看看后端是否支持cors方式(需要后端开启), 如果支持则保留这次请求的结果返回到回调函数, 否则舍弃掉所有数据直接报错
$.ajax({
url: "http://123.57.109.30:3006/api/getbooks",
type: "GET",
success (res) {
console.log(res);
}
})
11.4 跨域解决 - 服务器反向代理
- 刚刚我们请求的都是自己后端的接口, 现在请求网易新闻的接口
-
- 前端和网易新闻的域名不一致, 发生跨域访问, 默认被浏览器禁止掉
-
- 想使用jsonp方式, 但是你没办法去改人家网易的代码啊
-
- 所以采用反向代理, 找一个自己能控制的服务器(服务器去请求接口数据是可以的, 作为代理人, 前端请求自己的后端, 让后端作为代理人把数据拿回来返回给自己)
-
前提: 我知道别人的url可以拿到数据(注意在地址栏直接请求不算Ajax吧? 所以不会被浏览器禁止掉), 但是想用Ajax把数据请求回来铺设到自己的页面上 - 这个时候, 可以来个中介(自己能控制的服务器) 因为服务器之间请求是没有跨域限制的
// 如果后端不是我们自己的, 例如网页新闻接口(不能要求后端开启跨域)
// 我们可以自己弄一个服务器(用服务器作为代理人请求到数据, 自己服务器开启cors)
// 前端请求自己的服务器接口 - 把数据拿回来
$.ajax({
url: "http://123.57.109.30:3006/api/163news",
success (res) {
console.log(res);
}
})
12. axios
axios介绍
- axios 是一个专门用于调用后台接口的js库,后续Vue和React环境都可以使用它
- 支持客户端发送Ajax请求
- 支持服务端Node.js发送请求
- 支持Promise相关用法(解决回调地狱问题)
- 支持请求和响应的拦截器功能(登录时会用到)
- 可以手动取消请求
- 自动转换JSON数据(JSON.parse(res))
- 可以更加安全的处理请求
12.0 基本用法
- 用axios替代jQuery实现get和post方式请求
// 1. axios - get方式 - 查询书籍信息
axios({
method: 'get',
url: 'http://123.57.109.30:3006/api/getbooks',
params: {
id: 1,
bookname: '西游记'
}
}).then(function (res) {
console.log(res)
})
// 2. axios - post方式 - 新增书籍功能
document.getElementById("add").onclick = function () {
axios({
// 表示请求方式
method: 'post',
url: 'http://123.57.109.30:3006/api/addbook',
data: {
author: 'axios',
bookname: 'axios从入门到真香',
publisher: '自己出版的',
appkey: '7250d3eb-18e1-41bc-8bb2-11483665535a'
}
}).then(function (res) {
console.log(res)
})
}
12.1 提交二进制数据
var myFile = document.getElementById("myFile");
var btn = document.getElementById("btn");
btn.onclick = function () {
var fd = new FormData();
fd.append("img", myFile.files[0]);
fd.append('uname', 'lisi')
fd.append('pwd', '123')
axios({
// 表示请求方式
method: 'post',
url: 'http://123.57.109.30:3006/api/upload/avatar',
data: fd
}).then(function (res) {
console.log(res)
})
}
12.2 全局默认配置
- 配置基准URL地址
- 做项目时,基准一般配置一次即可,发送请求时找到url后面的路径即可
axios.defaults.baseURL = 'http://123.57.109.30:3006'
// 7250d3eb-18e1-41bc-8bb2-11483665535a
// 1. axios - get方式访问
axios({
// 表示请求方式
method: 'get',
url: '/api/getbooks',
params: {
id: 1,
bookname: '西游记'
}
}).then(function (res) {
console.log(res)
})
// 2. axios - post方式 - 新增书籍功能
document.getElementById("add").onclick = function () {
axios({
// 表示请求方式
method: 'post',
url: '/api/addbook',
data: {
author: 'axios',
bookname: 'axios从入门到真香',
publisher: '自己出版的',
appkey: '7250d3eb-18e1-41bc-8bb2-11483665535a'
}
}).then(function (res) {
console.log(res)
})
}
POST_请求参数格式总结
- application/x-www-form-urlencoded
- 表单的默认提交方式
- $.ajax的post默认提交方式
- multipart/form-data;
- 支持文件上传:new FormData()
- 也支持普通数据的提交,但是需要后端支持
- application/json
- 前端可以传递JSON字符串给后端
13. 异步编程
异步的概念
Ajax发送请求,浏览器不会阻塞(原因:内部采用了异步的方式发送请求)
-
如何理解同步和异步的概念
- 这两个概念是相对两个参与者来说的
-
思考如下的场景:你的同学(A)正在寝室玩游戏,你(B)在门口喊他去吃饭
- 场景一:A喊B去吃饭,B说等我一会,马上就结束了,此时A一直在门口等着,等B结束后,他们两个一块去食堂吃饭。(同步的,A阻塞了)
- 场景二:A喊B去吃饭,B说等我一会,马上就结束了,此时A说饿的顶不住了,我先去,待会你去找我,我在某一个桌位等你,然后B结束后去指定的位置找A。(异步的,A没有阻塞)
-
浏览器向服务器发送一个请求
- 场景一:浏览器向服务器发请求,服务器需要返回信息,如果服务器尚未返回信息,浏览器如果一直等着服务器返回,什么事情也不做(阻塞的)。(同步)
- 场景二:浏览器向服务器发请求,服务器需要返回信息,如果浏览器发出请求后,接着做别的事情,服务器返回信息后,才去通知浏览器进行处理,这种模式浏览器不阻塞。(异步)
13.0 异步数据获取方式
- 获取异步结果的问题:无法通过返回值得到异步的结果
console.log(123); // 先执行
setTimeout(function () {
// 注册定时器 - 最后执行
console.log("我是2秒后的异步代码");
}, 0);
var xhr = new XMLHttpRequest()
xhr.open('get', 'http://123.57.109.30:3006/api/getbooks')
xhr.send()
xhr.onreadystatechange = function () {
// 注册事件
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
}
console.log(456); // 主线程执行完毕
// 先确定作用域 - 变量提升 - 然后主线程执行
// 定时器最后执行 (事件函数要被触发-点击事件/Ajax请求事件)
13.1 异步返回结果正确姿势:回调函数
function myAjax(fn) {
var xhr = new XMLHttpRequest()
xhr.open('get', 'http://123.57.109.30:3006/api/getbooks')
xhr.send()
xhr.onreadystatechange = function () {
// 注册事件
if (xhr.readyState === 4 && xhr.status === 200) {
fn(JSON.parse(xhr.responseText));
}
}
}
myAjax(function(value){
// 空手进去, 满载而归
console.log(value);
})
- 案例补充 - 定时器返回数据 - return不出来了 - 就用回调函数
// 要求:定义一个函数,函数内部一份数据,要求一秒后从函数外得到
function getData (callback) {
var data = 'hello'
setTimeout(function () {
callback(data)
}, 3000)
}
getData(function (data) {
console.log(data)
})
异步原理分析
- JavaScript的运行是单线程的
- 为了防止单线程阻塞的问题,引入了事件队列(任务队列)机制
- 什么样的任务进入事件队列
- Ajax的回调函数(服务器有数据返回时:readyState发生变化时触发)
- 定时函数(满足延时时间后触发,但是不一定触发)
- 事件处理函数(特定事件发生时触发)
- 任务队列中的任务何时触发?
- 主线程必须是空闲的
- 特定条件触发
13.2 异步回调的嵌套问题
- 理解回调地狱的现象
function myAjax(url, data, fn){
$.ajax({
url: url,
data: data,
dataType: "json",
success (res) {
fn(res)
}
})
}
myAjax("http://123.57.109.30:3000/api/categoryFirst", {
}, function(obj){
var fId = obj['list'][0]['firstId'];
myAjax("http://123.57.109.30:3000/api/categorySecond", {
firstId: fId}, function(obj2){
var sId = obj2['list'][0]['secondId'];
myAjax("http://123.57.109.30:3000/api/categoryThird", {
secondId: sId}, function(obj3){
var tId = obj3['list'][0]['thiredId'];
myAjax("http://123.57.109.30:3000/api/goodslist", {
thirdId: tId}, function(obj4){
console.log(obj4);
})
})
})
})
- vue基础会学习Promise的用法 - 解决回调地域(把异步代码同步化)
14. 淘宝搜索案例
- 案例图示如下所示
14.0 案例 - 获取联想菜单
- 绑定输入事件并获取输入的值
// 1. 根据输入框的值 - 获取联想菜单
$("#ipt").on("input", function () {
var kw = $(this).val();
$.ajax({
// 请求地址
url: 'https://suggest.taobao.com/sug?q=' + encodeURI(kw),
// 返回数据格式
dataType: 'jsonp',
// 回调函数
success: function (data) {
$("#suggest-list").empty();
data.result.forEach(function(arr, index){
var theDiv = `<div class="suggest-item">${
arr[0]}</div>`;
$("#suggest-list").append(theDiv);
})
$("#suggest-list").show();
}
})
})
14.1 防抖函数使用
定时n秒, 到了才执行逻辑代码, 如果事件又触发了, 清除上一个定时器, 重新创建定时器 最后执行一次
// 1. 定时器
var timer = null;
// 根据输入框的值 - 获取联想菜单
$("#ipt").on("input", function () {
var kw = $(this).val();
// 2. 触发一次事件, 清空定时器 - 重新赋予一个(相当于重新计时)
clearTimeout(timer);
// 3. 如果不在触发事件, 那么3秒后执行逻辑代码
timer = setTimeout(function () {
$.ajax({
// 请求地址
url: 'http://123.57.109.30:3006/api/sug?q=' + encodeURI(kw),
// 返回数据格式
// 回调函数
success: function (data) {
$("#suggest-list").empty();
data.result.forEach(function (arr, index) {
var theDiv = `<div class="suggest-item">${
arr[0]}</div>`;
$("#suggest-list").append(theDiv);
})
$("#suggest-list").show();
}
})
}, 300);
});
14.2 缓存搜索结果
在程序运行期间, 用一个对象变量来保存搜索过的联想菜单关键字 - 下次再输入相同的直接用变量里, 而不用再去请求了
// 定时器
var timer = null;
// 1. 定义缓存对象
var obj = {
};
// 根据输入框的值 - 获取联想菜单
$("#ipt").on("input", function () {
var kw = $(this).val();
clearTimeout(timer);
timer = setTimeout(function () {
// 2. 判断如果对象里有那个数据, 直接使用铺设页面
if (obj[kw] !== undefined) {
$("#suggest-list").empty();
obj[kw].result.forEach(function (arr, index) {
var theDiv = `<div class="suggest-item">${
arr[0]}</div>`;
$("#suggest-list").append(theDiv);
})
$("#suggest-list").show();
} else {
$.ajax({
// 请求地址
url: 'http://123.57.109.30:3006/api/sug?q=' + encodeURI(kw),
// 返回数据格式
// 回调函数
success: function (data) {
$("#suggest-list").empty();
obj[kw] = data; // 3. 新的数据保存在逻辑变量obj上
data.result.forEach(function (arr, index) {
var theDiv = `<div class="suggest-item">${
arr[0]}</div>`;
$("#suggest-list").append(theDiv);
})
$("#suggest-list").show();
}
})
}
}, 300);
});
14.3 防抖函数 - 封装
// 定义缓存对象
var obj = {
};
// 根据输入框的值 - 获取联想菜单
$("#ipt").on("input", debounce(function () {
var kw = $(this).val();
// 判断如果对象里有那个数据, 直接使用铺设页面
if (obj[kw] !== undefined) {
$("#suggest-list").empty();
obj[kw].result.forEach(function (arr, index) {
var theDiv = `<div class="suggest-item">${
arr[0]}</div>`;
$("#suggest-list").append(theDiv);
})
$("#suggest-list").show();
} else {
$.ajax({
// 请求地址
url: 'http://123.57.109.30:3006/api/sug?q=' + encodeURI(kw),
// 返回数据格式
// 回调函数
success: function (data) {
$("#suggest-list").empty();
obj[kw] = data; // 新的数据保存在逻辑变量obj上
data.result.forEach(function (arr, index) {
var theDiv = `<div class="suggest-item">${
arr[0]}</div>`;
$("#suggest-list").append(theDiv);
})
$("#suggest-list").show();
}
})
}
}, 300));
// 2. 定义防抖的函数
function debounce(fn, theTime) {
return function () {
clearTimeout(fn.timer);
fn.timer = setTimeout(() => {
fn.call(this, ...arguments);
}, theTime);
}
}
15. 协议加强
这里是概念, 了解即可
15.0 什么是通信
通信, 就是信息的传递和交换
三要素:
- 通信的主体: 客户端(浏览器) 和 服务器
- 通信的内容: 客户端把内容 发给 服务器 / 服务器 返回内容给客户端
- 通信的方式: http通信协议
15.1 通信协议
协议:规定(规则)
- 通信主体双方 - 事先约定好的通信格式(内容格式) - 就叫做通信协议
15.2 http协议
通信的协议有很多种, 而http只是其中一种
HTTP HyperText Transfer Protocol 超文本传输协议 (浏览器和服务器之间传输的都叫超级文本(标签文本)
网页内容的传输 - 要遵守http协议的内容格式
- 它的交互模型是 请求 和 响应 的 一去一回的 动作
15.3 URL地址补充
如果想用http协议, 去请求一个服务器, 要先知道你要请求的服务器的地址:功能版本号, 功能路径等
URL地址补充
- URL的基本组成 schema://host:port/path?query#fragment
- schema 协议:http/https/file/ftp/smtp/pop3
- host 主机名(域名或者IP地址)IP(61.135.169.125)
- 用来唯一的区分互联网中某台计算机
- IP地址不好记住,所有有了域名
- port 端口,http协议的默认端口是80,作用:区分计算机中某个应用程序(0-65535)
- path 路径, /a/b/c/c 用来区分不同的资源 (与文件夹类似)
- query 查询字符串,uname=lisi&age=12 主要用于传递get参数
- fragment 锚点(hash 哈希),跳转到页面的某个位置
- 通过什么规则, 找到哪台电脑里的哪个应用程序, 路径下的某个功能, 以及给它传参
15.4 请求消息(报文)
由客户端, 发送的数据信息, 就叫请求消息(请求报文)
请求对象例子: (可以在浏览器发起ajax请求后) 在这里查看
1. POST /work/1.php HTTP1.1
2. Host:www.wrox.com
3. User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET
CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
4. Content-Type:application/x-www-form-urlencoded
5. Content-Length:40
6. Connection: Keep-Alive
7.
8. name=Professional_Ajax&publisher=Wiley&page=1
- 1行代码, 请求方法(POST), URL(/work/1.php), 协议版本HTTP1.1
- 2, 3, 4, 5, 6行代码, 请求头代码, 头部字段名: 对应的值
- 7行代码, 代表空行 (必须有的), 规定
- 8行代码, 请求发送的数据 (请求体) - body体
这是客户端 -> 服务器 发送数据
前端发给后台数据的方式: get(在url后面拼接要传递的参数), post(在body体力传输参数给后台), 请求头(设置请求头传递参数)
15.4.0 请求头
- User-Agent (浏览器相关信息 - 用户代理字符串)
- Content-Length (请求发送的参数内容长度)
- Content-Type (发送的参数内容的类型)
- Accept (客户端能够接受什么类型的数据作为返回内容)
15.4.1 请求体
GET方式没有请求体 / POST才有请求体
15.5 响应消息(报文)
在浏览器里观察响应头字段的值 -
响应对象例子:
1. HTTP/1.1 200 OK
2. Date: Fri, 22 May 2009 06:07:21 GMT
3. Content-Type: text/html; charset=UTF-8
4.
5. <html>
<head></head>
<body>
<!--body goes here-->
</body>
</html>
- 1行代码, 响应状态行, 协议, 响应状态码, 响应状态消息
- 2, 3行, 消息报头, 服务端返回给客户端使用的一些消息
- 4行, 空行(规定)
- 5行, 服务器给客户端/浏览器, 返回的正文数据
这是客户端 <- 服务器 返回的数据
15.5.0 响应头
Access-Control-Allow-Origin: * - 服务器允许哪写地址链接(跨域 请求)
Date: 服务器上现在的时间
Content-Type: 响应内容类型
Content-Length: 响应内容的大小
15.5.1 响应体
就是后台返回的内容类型
html标签字符串 / JSON字符串数据 / css代码 / js代码 / 图片 / …
15.6 请求方式
- 对服务器资源进行的操作
- 增删改查(CRUD-create-read-update-delete)
- 规范的接口设计会明确告诉你使用哪种请求方式
- GET 查询
- POST 添加
- PUT 修改
- DELETE 删除
- Restfull 形式的URL(相同的地址, 不同的方式对应不同的功能)
- http://abc.com/books GET 查询所有的图书列表
- http://abc.com/books POST 添加一本图书
- http://abc.com/books/123 DELTE 删除一本书(删除id是123的图书)
- http://abc.com/books/123 PUT 修改一本图书的信息(修改id是123的图书信息)
- http://abc.com/books/123/comment/456 DELETE (删除id是123的图书的id是456的评论信息)
15.7 响应状态码
- 标识服务端响应的状态(服务器告诉客户端请求响应的结果是什么情况)
- 2XX 表示服务端返回的数据是正常的(常见的是200)
- 4XX 客户端发生了错误,因为服务器对应的资源不存在(常见的是404)
- 5XX 服务器发生错误,服务器代码出错了(常见的是503)
- 3XX 重定向,服务器收到请求后,返回一个地址,让浏览器重新请求到另外一个地址 (这种是后台返回一个状态码304, 前端就会调用本地保存的缓存)
15.7.0 2xx
客户端相关成功的状态码
- 200 - 请求完全成功
- 201 - 服务器上已经创建了这个资源
15.7.1 3xx
客户端相关的状态码
15.7.2 4xx
客户端相关的错误状态码
15.7.3 5xx
服务器端相关的状态码
经验值
前端发送jsonp请求调用后台接口
- 前端发送请求调用jsonp接口,并且在浏览器的调试工具中能够看到数据返回了,格式(json)如下所示
- 但是在success中没有得到数据,为什么?因为接口有问题
- jsonp接口应该返回什么?函数调用
- 如何解决问题?
- 方法一:后端把接口调整为jsonp接口
- 方法二:后端配置cors,前端使用Ajax发请求
跨域Ajax接口的报错问题
- 如果Ajax调用的后端接口跨域了,并且后端没有解决跨域问题,那么前端就会报错
- 解决方案:让后端解决CORS或者反向代理;采用jsonp接口方案
如有不足,请多指教,
未完待续,持续更新!
大家一起进步!