后端传输流跨域_ajax异步请求和jsonp的跨域请求探讨

本文详细探讨了前端开发中与后端交互的关键技术——Ajax异步请求,包括GET和POST两种方式,以及如何使用FormData对象。此外,还深入讲解了JSONP的工作原理和应用场景,解释了其在后端不支持跨域时如何实现数据获取。
摘要由CSDN通过智能技术生成

一、学习的新认识

今天学习了前端中与后端交互的重要环节ajax异步请求,同时也学习了最流行的跨域方式JSONP。自己新的认识有以下几点:

json和js对象联系和区别 json是js提出的轻量级跨平台的数据交换/传输/存储格式,它解决了xml格式中标签过多导致网络传输量过大的问题,是目前最欢迎,支持最广的。不仅Javascript,其它如C、C++、C#、Java、PHP和Python都提供了编程接口对它的支持。

ajax的post请求三种方式 跟着老师理解了前端和后端交互的三种方式:是默认键值对方式、JSON方式和最简单的FormData对象方式,尤其是FormData方式是推荐方式,相比于普通ajax方式,它序列化数据直接被ajax识别传输,不用再要转为字符串,在后端也直接自动识别。

JSONP跨域请求 基于”同源策略”浏览器禁止使用JS脚本(Ajax)发起跨域请求,通过JSONP可以实现跨域请求数据,即使后端不支持跨域情况下。老师讲了JSONP的原理,但没讲怎么使用,我一直疑惑JSONP的回调函数的关键名从哪里来,直到在网上看了百度JSONP接口才明白。文中对后端跨域和JSONP跨域进行了区别,并实例演示了真实案例。

二、JSON

1、JSON是什么JSON: JavaScript Object Notation(JS 对象表示法)

跨平台跨语言的 轻量级数据交换/传输/存储格式 ,相比于XML,没有多余的标签,减少了数据体积,提高了效率。

JSON 独立于任何编程语言, 几乎所有编程语言都提供了访问JSON数据的API接口,如JS的JSON.parse和JSON.stringify,PHP的json_decode和json_encode。

尽管 JSON 与 JS 并无直接关系,但 JSON 在 JS 代码中应用最广泛

其实json就是字符串,不过它是符合json格式的字符串 ,有时我们称json为json字符串 。

JSON格式:

大括号或中括号 包裹。大括号 {}存储对象字面量 ,中括号 []存储数组字面量 。

键-值对 json中都是键值对表示数据,键和值以:冒号分隔 ,键值对以,逗号分隔 ,并且最后一个键值对后不能有逗号 。

键名必须用英文双引号 包裹。 不管键名是否合法的js标识符都要用双引号包裹键名,单引号和没有引号都不是json格式,这点要与js对象区别开来。

值可以是数值、字符串、布尔、null、对象和数组 注意没有undefined。

值是字符串时要用英文双引号 包裹。 js对象中可用单引号或双引号,在json中若值是字符串则必须要用双引号。

不能有注释 不能在json之间注释,因为它本身就是字符串,注释后就不符合json格式了。

2、js对象和json字符串

如下是典型的js对象定义:

constuser={

name:'woxiaoyao',

age:28,

"first job":'worker',

isJob:true,

comment:null,

}

转化为json字符串时,要除掉const user=,给所有键名加上双引号,值中有单引号改为双引号,最后一个逗号除掉。于是就是下面形式

{

"name":"woxiaoyao",

"age":28,

"first job":"worker",

"isJob":true,

"commen":null

}

在javascript中专门提供了两个方法实现了json字符串和js格式对象互转。

JSON.parse(jsonStr) 将json字符串转换为js对象

JSON.stringify(jsObj) 将js对象转换为json字符串

两者怎么记忆呢?我之前有时分不清,如果你像我一样,可这样记忆,因为string是字符串的意思,所有stringify最终结果是字符串,所有可以区分parse和stringify二个作用了。

三、ajax异步请求

Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式、快速动态网页应用的网页开发技术,无需重新加载整个网页的情况下,能够更新部分网页的技术。通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

它依赖XMLHttpRequest对象 ,XMLHttpRequest是浏览器提供的,处理异步请求的宿主对象,而非 JS 内置对象

1、ajax的GET请求ajax的GET请求流程:

创建请求对象: new XMLHttpRequest()

监听请求回调: onreadystatechange

初始化请求参数: open(请求类型,请求地址,是否异步)

发送请求: send()

前后端数据传输: json字符串 ,不同语言都支持json字符串

前后端数据处理: 接受到数据后先通过自己的JSON编程接口转为自己语言的对象,再进行处理。如javascript的JSON.parse()和PHP的json_decode()。

constform=document.querySelector('form');

constbtn=document.querySelector('button');

btn.addEventListener('click',ajaxGet,false);

// ajax的Get请求流程分四步:

// 1. 创建请求对象: `new XMLHttpRequest()`

constxhr=newXMLHttpRequest();

// 2. 监听请求回调: `onreadystatechange`

xhr.addEventListener('readystatechange',show,false);

functionajaxGet(ev){

if(form.children[1].value){

let url='data/index.php';

url=url.concat('?','name=',form.children[1].value);

// 3. 初始化请求参数: `open(请求类型,请求地址,是否异步)` true表示异步

xhr.open('GET',url,true);

// 4. 发送请求: `send()`

xhr.send();

}

}

functionshow(ev){

if(xhr.readyState==4){

// 返回的数据在xhr.responseText

console.log(xhr.responseText);

}

}

b00ecd035ed06bedcad442d29f641fa3.png

2、ajax的POST请求ajax的POST请求流程:

创建请求对象: new XMLHttpRequest()

监听请求回调: onreadystatechange

初始化请求参数: open(请求类型,请求地址,是否异步)

设置请求头: setRequestHeader()

发送请求: send()

post 与 get 相比, 多了一步: 设置请求头

前后端数据传输: json字符串 ,不同语言都支持json字符串,调用接口转为JSON字符串再传输。如JSON.stringify和PHP的json_encode()。

前后端数据处理: 接受到数据后先通过自己的JSON编程接口转为自己语言的对象,再进行处理。如javascript的JSON.parse()和PHP的json_decode()。

请求方式:json 数据以表单数据类型发送, 前端请求头是application/x-www-form-urlencoded, 后端用$_POST 接收。

json 数组就是以JSON发送, 前端请求头是application/json;charset=utf-8(json只支持utf-8编码), 后端用php://input 流文件方式接收

constform=document.querySelector('form');

constbtn=document.querySelector('button');

btn.addEventListener('click',ajaxPost,false);

// ajax的Post请求流程分五步:

// 1. 创建请求对象: `new XMLHttpRequest()`

constxhr=newXMLHttpRequest();

// 2. 监听请求回调: `onreadystatechange`

xhr.addEventListener('readystatechange',show,false);

functionajaxPost(ev){

let url='data/index2.php';

// 3. 初始化请求参数: `open(请求类型,请求地址,是否异步)` true表示异步

xhr.open('POST',url,true);

// 4. 设置请求头: `setRequestHeader()`

// 第一种:以表单键值对的方式发送数据

// xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');

// 第二种:以json方式发送

xhr.setRequestHeader('content-type','application/json;charset=utf-8');

let $user={

name:'admin',

password:'123456',

};

// 转换为json字符串

let data=JSON.stringify($user);

// 5. 发送请求: `send()`

xhr.send(data);

}

functionshow(ev){

if(xhr.readyState==4){

// 返回的数据在xhr.responseText

console.log(xhr.responseText);

}

}

e4299f1faee67efe510e9e91a67d781c.png

3、FormData对象

前端ajax的post请求时能不能不写请求头, 服务器端php还能用$_POST来接收呢?答案是可以的,就是使用FormData对象直接序列化表单数据,将表单数据进行封装后统一提交,可直接被 Ajax 识别,所以可以不设置请求头。除了表单数据外,也可用于普通数据。

// 第三种:formData对象方式,不用设置请求头,由浏览器自行判定,上面代码中请求可不用设置,数据直接通过FormData提交。

constform=document.querySelector('form');

constbtn=document.querySelector('button');

btn.addEventListener('click',ajaxPost,false);

// ajax的Post请求流程分五步:

// 1. 创建请求对象: `new XMLHttpRequest()`

constxhr=newXMLHttpRequest();

// 2. 监听请求回调: `onreadystatechange`

xhr.addEventListener('readystatechange',show,false);

functionajaxPost(ev){

let url='data/index2.php';

// 3. 初始化请求参数: `open(请求类型,请求地址,是否异步)` true表示异步

xhr.open('POST',url,true);

// 4. 发送请求: `send()`

// 第三种:formData对象方式,不用设置请求头,由浏览器自行判定,

xhr.send(newFormData(form));

}

functionshow(ev){

if(xhr.readyState==4){

// 返回的数据在xhr.responseText

console.log(xhr.responseText);

}

}

FormData是XMLHttpRequest 2级定义的,它是为序列化表以及创建与表单格式相同的数据提供便利。

利用一些键值对来模拟一系列表单控件:即将form中的所有表单元素的name和value组装成一个queryString;

异步上传二进制文件。

与普通Ajax相比,使用FormData的最大优点:可以异步上传二进制文件。

下面对FormData对象进行拓展介绍

创建FormData对象方式:

let formdata = new FormData(); 创建一个空的FormData对象,可以使用formdata.append(key,value)来添加数据。

let formdata = new FormData(form); 使用已有的表单来初始化一个FormData对象。

操作方法:

获取数据formdata.get(key)

formdata.get(“username”); //获取key为username的第一个值

formdata.getAll(“username”); //获取key为username的所有值,返回一个数组

添加数据formdata.append(key,value)

formdata.append(“k1”,”v1”);

formdata.append(“k1”,”v2”);

formdata.append(“k2”,”v2”);

formdata.getAll(“k1”); //[“v1”,”v2”]

formdata.get(“k2”); //“v2”

设置/修改数据formdata.set(key,value) 如果key不存在则新增一条数据,如果存在,则会修改对应的value值。

formdata.append(“k1”,”v1”);

formdata.set(“k1”,”v2”);

formdata.get(“k1”); //“v2”

判断是否存在某条数据formdata.has(key) ,存在返回true,不存在返回false。

formdata.append(“k1”,”v1”);

formdata.has(“k1”); //true

formdata.has(“k2”); //false

删除数据formdata.delete(key)

formdata.append(“k1”,”v1”);

formdata.delete(“k1”);

formdata.get(“k1”); //null

遍历 通过entries()或values()来获取一个遍历器

formdata.append(“k1”,”v1”);

formdata.append(“k2”,”v2”);

for(let [key,value] of formdata.entries()){

console.log(key +”:”+ value)

}

const btn = document.querySelector("#upload-btn");

btn.onclick = function(){

let file = document.querySelector("#upload");

let formdata = new FormData();

formdata.append("file",file.files[0]);

fetch("https://www.baidu.com",{

method:'POST',

body:formdata

}).then(d=>{

console.log("result is" + d);

alert("上传成功");

})

}

四、JSONP实现跨域请求跨域请求:

为了安全, 通过脚本发起的请求必须基于”同源策略”

浏览器禁止使用 JS 脚本(Ajax)发起跨域请求(跨域资源共享)

但是通过html中带有src属性的标签跨域请求不能禁止的,毕竟这是互联网发明初衷。

同源策略: 协议, 域名, 端口 三者完全相同, 则认为他们遵循了”同源策略”,否则如下面则认为不同源。

协议不同(http和https)

https://www.php.cn:443 /course/812.html

http:// www.php.cn:443 /course/812.html

1、JSONP原理演示JSONP:(JSON with Padding)

script标签允许跨域请求脚本:

动态生成

在跨域访问的服务器脚本中(如 php),将数据转为 json 格式,直接返回给前端处理就可以了

名字:

密码:

跨域请求

constform=document.querySelector('form');

constbtn=document.querySelector('button');

btn.addEventListener('click',createScript,false);

functioncreateScript(){

constscript=document.createElement('script');

let name=form.children[1].value;

if(name.length<1)returnfalse;

script.src=`http://blog.io/index.php?name=${name}&jsonp=show`;

document.head.appendChild(script);

}

functionshow(data){

console.log(data);

form.children[3].value=data.email;

}

// 后端

$users=[

['id'=>1,'name'=>'admin','email'=>'admin@php.cn'],

['id'=>2,'name'=>'peter','email'=>'peter@php.cn'],

['id'=>3,'name'=>'jack','email'=>'jack@php.cn'],

];

// 查询条件

$name=$_GET['name'];

// js回调

$callback=$_GET['jsonp'];

foreach($usersas$user){

if($user['name']==$name){

$result=$user;

break;

}

}

$data=json_encode($result);

// 创建一条js函数的调用语句返回

// echo "函数名(参数)";

echo"{$callback}({$data})";

f41e3b84bbe86a904767ff2650d37e58.gif

2、 JSONP的应用场景

写这篇文章之前这个问题深深困扰着我,老师只介绍了JSONP的原理,对其应用只是一句话带过,说可以查询天气。因为我是做后端的,知道RestfulAPI一般都会设置支持跨域,其实PHP支持跨域很简单,就是在PHP源码中加上下面代码就可以了,也就是CORS。

// 跨域请求

header('Content-Type: text/html;charset=utf-8');

// 代表允许任何网址请求

header('Access-Control-Allow-Origin:*');

// 允许请求的类型

header('Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE');

// 设置是否允许发送 cookies

header('Access-Control-Allow-Credentials: true');

// 设置允许自定义请求头的字段

header('Access-Control-Allow-Headers: Content-Type,Content-Length,Accept-Encoding,X-Requested-with, Origin');

对于后端支持跨域请求的,就没必要在前端再跨域请求了,那么后端不支持跨域请求的,如天气网站的数据,我们JSONP的回调函数的键名如何得到,是后端公开吗?明显不可能,还有就是API的格式。最后我在一篇介绍各搜索引擎的JSONP时才发现,JSONP能工作要有以下几点:

首先要抓取提供JSONP服务的api,包括关键字和回调键名,这样我们可以提供查询数据和声明回调函数。

通过上面JSONP的script的创建,模拟后端合法的用户 ,后端在执行echo时会调用我们的声明函数,从而得到数据。

对于不提供JSONP服务的,如主流的RestfulAPI的,JSONP就没办法了。

下面实战演示搜索时调用百度的搜索词联想功能

*{

margin:0px;

padding:0px;

}

li{

list-style:none;

}

#wrap {

width:600px;

height:40px;

margin:100pxauto;

}

#text {

width:500px;

height:34px;

margin:0auto;

line-height:34px;

}

#list {

width:500px;

border:1pxsolid#ccc;

}

#list > li {

width:500px;

height:30px;

line-height:30px;

}

#list > li > a {

text-decoration:none;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值