没用过裸的Ajax 也没听过jsonp,也不了解跨域问题,emmm…

参考:

http://www.runoob.com/ajax/ajax-tutorial.html

https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001434499861493e7c35be5e0864769a2c06afb4754acc6000

https://segmentfault.com/a/1190000015597029

http://ghmagical.com/article/page/id/AASiankfBJWp

Ajax,Asynchronous JavaScript and XML,直译就是异步的JavaScript和XML,其实就是使用JavaScript执行异步网络请求,不局限XML,可以有多种格式。

好处就是使用js获取数据,再用js更新页面,就不需要刷新,重新加载整个页面了。

Ajax使用XMLHttpRequest与后台进行交互

其实Ajax的实现代码真的很简单… (刚好在开一个9002端口的后台服务……

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="info"></div>
<script>
function success(text) {
const infoDiv = document.getElementById('info')
infoDiv.innerHTML = text
console.log('success:' + text)
} function fail(code) {
const infoDiv = document.getElementById('info')
infoDiv.innerHTML = code
console.log('fail:' + code)
} var request;
/**
* 对于低版本的IE,需要换一个 ActiveXObject 对象
* 通过检测 window 对象是否有 XMLHttpRequest 属性来确定浏览器是否支持标准的 XMLHttpRequest
*/
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
} else {
request = new ActiveXObject('Microsoft.XMLHTTP');
} request.onreadystatechange = function () { // 状态发生变化时,函数被回调
if (request.readyState === 4) { // 成功完成
// 判断响应结果:
if (request.status === 200) {
// 成功,通过responseText拿到响应的文本:
return success(request.responseText);
} else {
// 失败,根据响应码判断失败原因:
return fail(request.status);
}
} else {
// HTTP请求还在继续...
}
} // 发送请求:
request.open('GET', 'http://127.0.0.1:9002/user/info');
request.send();
</script>
</body>
</html>

其中的函数

open(method, url, async)
method:请求的类型;GET 或 POST
url:文件在服务器上的位置
async:true(异步)或 false(同步) send(string)
string:仅用于 POST 请求 setRequestHeader(header,value)
向请求添加 HTTP 头。
header: 规定头的名称
value: 规定头的值 例
xmlhttp.open("POST","/try/ajax/demo_post2.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Henry&lname=Ford");

至于 onreadystatechange 肯定就是一个回调函数啦,每当 readyState 属性改变时,就会调用该函数。那个…异步才需要回调函数嘛…

readyState 含义

0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪

status 含义(就是HTTP状态码

200:服务器响应正常。
304:该资源在上次请求之后没有任何修改(这通常用于浏览器的缓存机制,使用GET请求时尤其需要注意)。
400:无法找到请求的资源。
401:访问资源的权限不够。
403:没有权限访问资源。
404:需要访问的资源不存在。
405:需要访问的资源被禁止。
407:访问的资源需要代理身份验证。
414:请求的URL太长。
500:服务器内部错误。

responseText 和 responseXML

responseText: 获得字符串形式的响应数据。
responseXML: 获得 XML 形式的响应数据。

然后就是跨域问题。

Failed to load http://b: ... has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://a' is therefore not allowed access.

首先要知道跨域问题是因为浏览器的安全策略:同源策略。

默认情况下,JavaScript在发送AJAX请求时,URL的域名必须和当前页面完全一致。域名,协议,端口号都要相同。

也就是说小一去访问小夏,然而小夏家有防盗门,进不去。你总不能怪别人有防盗门吧。这时小一一个人,无论做什么都是没办法进去的,想要进去,只有小夏帮你。你们对个暗号,小夏帮你开门,或者小夏给你钥匙,录个指纹之类的。

同理,跨域问题,光靠前端是没办法解决的,有了后端帮助才可以解决,比如把门打开……嗯……

1. CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

我的理解就是在后台配置一下…………比如我用Spring Boot写的后台代码……

@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}

正常点……

根据报错就可以看出 a 网站想访问 b, 但是 b 的响应中 Access-Control-Allow-Origin 字段并不包含 a 的域名,访问失败。

对于简单请求,定义如下:

请求方法是以下三种方法之一:HEAD、GET、POST

HTTP 的头信息不超出以下几种字段:Accept、Accept-Language、Content-Language、Last-Event-ID

Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

只需要合理设置 Access-Control-Allow-Origin 即可。

对于非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)这种情况下除了设置origin,还需要设置Access-Control-Request-Method以及Access-Control-Request-Headers

。。。。xx

2. 还有一种解决方式是代理,前端把请求发给同域的代理服务器,代理服务器再转发给真正的服务器。

3. 就是我要学习的JSONP了,它有个限制,只能用GET请求,并且要求返回JavaScript。这种方式跨域实际上是利用了浏览器允许跨域引用JavaScript资源。

通过js创建一个script标签然后添加src,这样就会调用这个src的请求,所以只能是get请求。其实真的也是很简单的~前端页面:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jsonp</title>
</head>
<body>
<span>从后台获取数据:</span>
<div id="data"></div>
<script>
function foo(data) {
console.log('通过jsonp获取后台数据:', data)
document.getElementById('data').innerHTML = data
}
(function jsonp() {
let head = document.getElementsByTagName('head')[0] // 获取head元素 把js放里面
let js = document.createElement('script')
js.src = 'http://127.0.0.1:9002/testJSONP?a=1&b=2&callback=foo'
head.appendChild(js)
})()
</script>
</body>
</html>

后端返回数据用 callback() 包裹起来,这样就相当于返回的那个js文件在调用 callback 函数,需要的逻辑直接写到指定的 callback 函数就可以了,很机智的方法。

@RequestMapping(value="/testJSONP", method = RequestMethod.GET)
public String testJSONP(String callback, Integer a, Integer b) {
return callback + '(' + (a + b) + ')';
}

请求信息

返回一个字符串

抄一遍大神把ajax和jsonp合一起的代码,不到100行,很简单。

function ajax(params) {

    params = params || {}
params.data = params.data || {} params.jsonp ? jsonp(params) : json(params) // 根据params中是否有jsonp参数判断是不是jsonp请求 function json(params) {
params.type = (params.type || 'GET').toUpperCase() // 默认使用get方法
params.data = formatParams(params.data) // 把参数对象改为参数字符串
let xhr = new XMLHttpRequest()
xhr.onreadystatechange = function() {
// readyState 属性表示请求/响应过程的当前活动阶段 4为完成 已经接收到全部响应数据
if (xhr.readyState === 4) {
let status = xhr.status
if (status >= 200 && status < 300) {
let response = ''
// 判断接受数据的内容类型
let type = xhr.getResponseHeader('Content-Type')
if (type.indexOf('xml') !== -1 && xhr.responseXML) {
response = xhr.responseXML
} else if (type === 'application/json') {
response = JSON.parse(xhr.responseText)
} else {
response = xhr.responseText
}
params.success && params.success(response)
} else {
params.error && params.error(status)
}
}
}
// 如果是get就把参数放在url 否则放在body
if (params.type === 'GET') {
xhr.open(params.type, params.url + '?' + params.data, true)
xhr.send()
} else {
xhr.open(params.type, params.url, true)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
xhr.send(params.data)
}
} function jsonp(params) {
let callbackName = params.jsonp
let head = document.getElementsByTagName('head')[0]
params.data['callback'] = callbackName
let data = formatParams(params.data)
let script = document.createElement('script')
head.appendChild(script) window[callbackName] = function(json) {
head.removeChild(script)
clearTimeout(script.timer)
window[callbackName] = null
params.success && params.success(json)
} script.src = params.url + '?' + data if (params.time) {
script.timer = setTimeout(() => {
head.removeChild(script)
window[callbackName] = null
params.error && params.error({ message: '超时' })
}, params.time)
}
} function formatParams(data) {
let arr = []
for (let name in data) {
arr.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name]))
}
// 添加一个随机数 防止缓存
arr.push('v=' + random())
return arr.join('&')
} function random() {
return Math.floor(Math.random() * 10000 + 500)
} }

Ajax,JSONP以及跨域问题的更多相关文章

  1. ajax jsonp的跨域请求

    1.页面ajax的请求 $.ajax({ async: false, url: 'http://localhost:8080/downloadVideos',//跨域的dns/document!sea ...

  2. PHP AJAX JSONP实现跨域请求使用实例

    在之前我写过“php返回json数据简单实例”,“php返回json数据中文显示的问题”和“在PHP语言中使用JSON和将json还原成数组”.有兴趣的童鞋可以看看 今天我写的是PHP AJAX JS ...

  3. C# WebClient、jQuery ajax jsonp实现跨域

    WebClient 无传输数据获取 Uri uri = new Uri(allURL); WebClient wc = new WebClient(); wc.Encoding = System.Te ...

  4. ajax jsonP 解决跨域问题

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. AJAX跨域问题解决方法(2)——JSONP解决跨域

    JSONP是什么?JSON全称为JSON with Padding,是JSON的一种补充的使用方式,不是官方协议. 使用JSONP服务器后台要改动吗?JSONP不同于一般的ajax请求返回json对象 ...

  6. JSONP实现跨域

    首先提出:什么是跨域?如何解决跨域? 跨域可以简单的理解为从一个域名访问另一个域名,由于javascript的同源政策的限制,出于安全的考虑,不允许浏览器这么做.比如a.com 域名下的js无法操作b ...

  7. 跨域解决方案二:使用JSONP实现跨域

    跨域的实现方式有多种,除了 上篇文章 提到的CORS外,常见的还有JSONP.HTML5.Flash.iframe.xhr2等. 这篇文章对JSONP的跨域原理进行了探索,并将我的心得记录在这里和大家 ...

  8. Ajax如何实现跨域问题

    一个域名的组成 http:// www . abc.com : 8080 /scripts/jquery.js 协议 子域名 主域名 端口号 请求资源地址 当协议.子域名.主域名.端口号中任意一个不同 ...

  9. 转(JSONP处理跨域事件)

     前言: 由于Sencha Touch 2这种开发模式的特性,基本决定了它原生的数据交互行为几乎只能通过AJAX来实现. 当然了,通过调用强大的PhoneGap插件然后打包,你可以实现100%的Soc ...

随机推荐

  1. odoo8 元素简介

    一:模型module: 1. 字段类型 (1)可控字段: fileds.char() fileds.Boolean() fileds.Date() (2)保留字段:(系统自动生成) id (Id) t ...

  2. 当Vue中img的src是动态渲染时不显示问题

    最近遇见动态渲染img时,想起了当初刚开始写vue时,曾经遇见的一个小小坑. Vue中:img的src属性是动态渲染时不显示问题1.需求:展示用户头像,数据从后台获取,如果没有拿到则显示默认图片. 如 ...

  3. ListView点击事件失效(item里面有button按钮控件)解决方法

    ListView点击事件失效解决方法: 一般出现这个情况,就是你的item里面有按钮的点击事件,你的item里面有button控件,button控件是抢占焦点的,只要在你的item布局里面这样子写就可 ...

  4. 关于TypeError: strptime() argument 1 must be str, not bytes解析

    关于TypeError: strptime() argument 1 must be str, not bytes解析   在使用datetime.strptime(s,fmt)来输出结果日期结果时, ...

  5. 20155312 张竞予 Exp3 免杀原理与实践

    Exp3 免杀原理与实践 目录 基础问题回答 (1)杀软是如何检测出恶意代码的? (2)免杀是做什么? (3)免杀的基本方法有哪些? 实验总结与体会 实践过程记录 正确使用msf编码器,msfveno ...

  6. LOJ-10092(最大半连通子图)

    题目连通:传送门 思路: 题目定义很清晰,然后就不会了QAQ…… 后来看了书,先缩点,然后再用拓扑排序找到最长的链子的节点数(因为缩点后所有点都是一个强连通分量,所以找最长的链子就是最大限度包含 点的 ...

  7. 2019浙江省赛K zoj4110 Strings in the Pocket(manachar)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=6012 题意 给你两个串,可以翻转a串的一个区间,问有多少对l,r使得翻转后的a ...

  8. 在idea中,mavne项目使用mybatis-generator-maven-plugin自动生成实体了的时候,在maven插件里面始终不显示

    最近想学习mybatis的知识,自己搭了个简单的ssm框架,想通过插件自动生成实体类,发现想要的插件一直都没显示出来,着实很郁闷: pom.xm中的配置: <!--mybatis-generat ...

  9. Python开发——8.模块

    一.模块 1.模块 (1)定义:一个.py文件就是一个模块 (2)原因:为了防止程序代码越来越长,对函数进行分组放到不同的文件夹里. (3)优点:提高代码的可维护性:模块编写完毕可以被别人引用,也可以 ...

  10. retrofit+rxjava封装

    public class RetrofitHelper { private static OkHttpClient okHttpClient; private static ServiceAPI se ...