Home  >  Article  >  Web Front-end  >  Detailed explanation of ajax and same origin strategy implemented by JS

Detailed explanation of ajax and same origin strategy implemented by JS

小云云
小云云Original
2018-05-30 11:59:111701browse

JS and Ajax are both essential in our programs, and they are also closely related. In this article, we mainly share with you examples of ajax and same-origin strategy implemented in JS. It has a good reference value and we hope it can help everyone.

1. Review ajax implemented by jQuery

First let’s talk about the advantages and disadvantages of ajax

Advantages:

AJAX uses Javascript technology to send asynchronous requests to the server;

AJAX does not need to refresh the entire page;

Because the server response content is no longer the entire page, but a part of the page, AJAX performance is high;

ajax implemented by jquery

index. html





 
 Title
 

Views.py

import json,time
 
def index(request):
 
 return render(request,"index.html")
 
def handle_Ajax(request):
 
 username=request.POST.get("username")
 password=request.POST.get("password")
 
 print(username,password)
 time.sleep(10)
 
 return HttpResponse(json.dumps("Error Data!"))

$.ajax parameters

Request parameters

######################------------data---------################

  data: 当前ajax请求要携带的数据,是一个json的object对象,ajax方法就会默认地把它编码成某种格式
    (urlencoded:?a=1&b=2)发送给服务端;此外,ajax默认以get方式发送请求。

    function testData() {
    $.ajax("/test",{  //此时的data是一个json形式的对象
     data:{
     a:1,
     b:2
     }
    });     //?a=1&b=2
######################------------processData---------################

processData:声明当前的data数据是否进行转码或预处理,默认为true,即预处理;if为false,
    那么对data:{a:1,b:2}会调用json对象的toString()方法,即{a:1,b:2}.toString()
    ,最后得到一个[object,Object]形式的结果。
   
######################------------contentType---------################

contentType:默认值: "application/x-www-form-urlencoded"。发送信息至服务器时内容编码类型。
    用来指明当前请求的数据编码格式;urlencoded:?a=1&b=2;如果想以其他方式提交数据,
    比如contentType:"application/json",即向服务器发送一个json字符串:
    $.ajax("/ajax_get",{
    
     data:JSON.stringify({
      a:22,
      b:33
     }),
     contentType:"application/json",
     type:"POST",
    
    });       //{a: 22, b: 33}

    注意:contentType:"application/json"一旦设定,data必须是json字符串,不能是json对象

    views.py: json.loads(request.body.decode("utf8"))


######################------------traditional---------################

traditional:一般是我们的data数据有数组时会用到 :data:{a:22,b:33,c:["x","y"]},
    traditional为false会对数据进行深层次迭代;

Response parameters

/*

dataType: 预期服务器返回的数据类型,服务器端返回的数据会根据这个值解析后,传递给回调函数。
   默认不需要显性指定这个属性,ajax会根据服务器返回的content Type来进行转换;
   比如我们的服务器响应的content Type为json格式,这时ajax方法就会对响应的内容
   进行一个json格式的转换,if转换成功,我们在success的回调函数里就会得到一个json格式
   的对象;转换失败就会触发error这个回调函数。如果我们明确地指定目标类型,就可以使用
   data Type。
   dataType的可用值:html|xml|json|text|script
   见下dataType实例

*/

small Exercise: Calculate the sum of two numbers

Method 1: No contentType is specified here: the default is urlencode

index.html




 
 
 
 Title
 
 

计算两个数的和,测试ajax

+=

views.py

def index(request):
 return render(request,"index.html")

def sendAjax(request):
 print(request.POST)
 print(request.GET)
 print(request.body) 
 num1 = request.POST.get("num1")
 num2 = request.POST.get("num2")
 ret = float(num1)+float(num2)
 return HttpResponse(ret)

Method 2: Specify conentType as json data to send:

index2. html

views.py

def sendAjax(request):
 import json
 print(request.POST) #
 print(request.GET) #
 print(request.body) #b'{"num1":"2","num2":"2"}' 注意这时的数据不再POST和GET里,而在body中
 print(type(request.body.decode("utf8"))) # 
 # 所以取值的时候得去body中取值,首先得反序列化一下
 data = request.body.decode("utf8")
 data = json.loads(data)
 num1= data.get("num1")
 num2 =data.get("num2")
 ret = float(num1)+float(num2)
 return HttpResponse(ret)


2. Ajax implemented by JS

1. AJAX core (XMLHttpRequest)

In fact, AJAX adds one more object to Javascript: the XMLHttpRequest object. All asynchronous interactions are done using the XMLHttpServlet object. In other words, we only need to learn a new object of Javascript.

var xmlHttp = new XMLHttpRequest(); (Most browsers support the DOM2 specification)

Note that each browser’s support for XMLHttpRequest is also different! In order to deal with browser compatibility issues, the following method is given to create an XMLHttpRequest object:

function createXMLHttpRequest() {
    var xmlHttp;
    // 适用于大多数浏览器,以及IE7和IE更高版本
    try{
      xmlHttp = new XMLHttpRequest();
    } catch (e) {
      // 适用于IE6
      try {
        xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
      } catch (e) {
        // 适用于IE5.5,以及IE更早版本
        try{
          xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (e){}
      }
    }      
    return xmlHttp;
  }

2. Usage process

1. Open the connection with the server (open)

After getting the XMLHttpRequest object, you can call the open() method of the object to open the connection with the server. The parameters of the open() method are as follows:

open(method, url, async):

method: request method, usually GET or POST;

url: requested Server address, for example: /ajaxdemo1/AServlet. If it is a GET request, you can also add parameters after the URL;

async: This parameter does not need to be given. The default value is true, indicating an asynchronous request;

var xmlHttp = createXMLHttpRequest();

xmlHttp.open("GET", "/ajax_get/?a=1", true);

2. Send request

After using open to open the connection, you can call the send() method of the XMLHttpRequest object to send the request. The parameters of the send() method are POST request parameters, which correspond to the request body content of the HTTP protocol. If it is a GET request, the parameters need to be connected after the URL.

Note: If there are no parameters, null needs to be given as the parameter! If null is not given as a parameter, the FireFox browser may not be able to send requests normally!

xmlHttp.send(null);

3. Receive the server’s response (5 states, 4 processes)

When the request is sent out After that, the server side starts execution, but the response from the server side has not been received yet. Next we receive the response from the server.

The XMLHttpRequest object has an onreadystatechange event, which is called when the state of the XMLHttpRequest object changes. The following introduces the five states of the XMLHttpRequest object:

0: The initialization is not completed, the XMLHttpRequest object has only been created, and the open() method has not been called;
1: The request has started, the open() method has not been called Has been called, but the send() method has not been called;
2: Request sending completion status, the send() method has been called;
3: Start reading the server response;
4: End of reading the server response .

The onreadystatechange event will be triggered when the state is 1, 2, 3, or 4.

The following code will be executed four times! Corresponding to the four states of XMLHttpRequest!

xmlHttp.onreadystatechange = function() {
      alert('hello');
    };

But usually we only care about the last state, that is, the client will not make changes until the end of reading the server response. We can get the status of the XMLHttpRequest object through the readyState attribute of the XMLHttpRequest object.

xmlHttp.onreadystatechange = function() {
      if(xmlHttp.readyState == 4) {
        alert('hello');  
      }
    };

In fact, we also need to care about whether the status code xmlHttp.status of the server response is 200. If the server response is 404 or 500, it means that the request failed. We can get the server's status code through the status attribute of the XMLHttpRequest object.

Finally, we also need to obtain the content of the server response, which can be obtained through the responseText of the XMLHttpRequest object.

xmlHttp.onreadystatechange = function() {
      if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
        alert(xmlHttp.responseText);  
      }
    };

Note:

If it is a post request:

基于JS的ajax没有Content-Type这个参数了,也就不会默认是urlencode这种形式了,需要我们自己去设置
<1>需要设置请求头:xmlHttp.setRequestHeader(“Content-Type”, “application/x-www-form-urlencoded”);
注意 :form表单会默认这个键值对不设定,Web服务器会忽略请求体的内容。

<2>在发送时可以指定请求体了:xmlHttp.send(“username=yuan&password=123”)

基于jQuery的ajax和form发送的请求,都会默认有Content-Type,默认urlencode,

Content-Type:客户端告诉服务端我这次发送的数据是什么形式的
dataType:客户端期望服务端给我返回我设定的格式

If it is a get request:

 xmlhttp.open("get","/sendAjax/?a=1&b=2");

Small exercise: Same as the above exercise, just in a different way (you can compare it with jQuery)

views.py

def sendAjax(request):
  num1=request.POST.get("num1")
  num2 = request.POST.get("num2")
  ret = float(num1)+float(num2)
  return HttpResponse(ret)

JS实现ajax小结

创建XMLHttpRequest对象;
  调用open()方法打开与服务器的连接;
  调用send()方法发送请求;
  为XMLHttpRequest对象指定onreadystatechange事件函数,这个函数会在

  XMLHttpRequest的1、2、3、4,四种状态时被调用;

  XMLHttpRequest对象的5种状态,通常我们只关心4状态。

  XMLHttpRequest对象的status属性表示服务器状态码,它只有在readyState为4时才能获取到。

  XMLHttpRequest对象的responseText属性表示服务器响应内容,它只有在
  readyState为4时才能获取到!

总结:

- 如果"Content-Type"="application/json",发送的数据是对象形式的{},需要在body里面取数据,然后反序列化
= 如果"Content-Type"="application/x-www-form-urlencoded",发送的是/index/?name=haiyan&agee=20这样的数据,
 如果是POST请求需要在POST里取数据,如果是GET,在GET里面取数据

实例(用户名是否已被注册)

7.1 功能介绍

在注册表单中,当用户填写了用户名后,把光标移开后,会自动向服务器发送异步请求。服务器返回true或false,返回true表示这个用户名已经被注册过,返回false表示没有注册过。

客户端得到服务器返回的结果后,确定是否在用户名文本框后显示“用户名已被注册”的错误信息!

7.2 案例分析

页面中给出注册表单;

在username表单字段中添加onblur事件,调用send()方法;

send()方法获取username表单字段的内容,向服务器发送异步请求,参数为username;

django 的视图函数:获取username参数,判断是否为“yuan”,如果是响应true,否则响应false

参考代码:



//--------------------------------------------------index.html

注册

用户名:
密 码:
//--------------------------------------------------views.py from django.views.decorators.csrf import csrf_exempt def login(request): print('hello ajax') return render(request,'index.html') # return HttpResponse('helloyuanhao') @csrf_exempt def ajax_check(request): print('ok') username=request.POST.get('username',None) if username=='yuan': return HttpResponse('true') return HttpResponse('false')

三、同源策略与jsonp

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
jsonp(jsonpadding)

之前发ajax的时候都是在自己给自己的当前的项目下发

现在我们来实现跨域发。给别人的项目发数据,

创建两个项目,先来测试一下

项目一:


项目一

项目二:

=========================index.html===============

项目二

=========================views=============== from django.shortcuts import render,HttpResponse # Create your views here. def index(request): return render(request, "index.html") def ajax_send2(request): print(222222) return HttpResponse("hello")

出现了一个错误,这是因为同源策略给限制了,这是游览器给我们报的一个错

(但是注意,项目2中的访问已经发生了,说明是浏览器对非同源请求返回的结果做了拦截。)

注意:a标签,form,img标签,引用cdn的css等也属于跨域(跨不同的域拿过来文件来使用),不是所有的请求都给做跨域,(为什么要进行跨域呢?因为我想用人家的数据,所以得去别人的url中去拿,借助script标签)

如果用script请求的时候也会报错,当你你返回的数据是一个return Httpresponse(“项目二”)只是一个名字而已,js中如果有一个变量没有声明,就会报错。就像下面的这样了

只有发ajax的时候给拦截了,所以要解决的问题只是针对ajax请求能够实现跨域请求

解决同源策源的两个方法:

1、jsonp(将JSON数据填充进回调函数,这就是JSONP的JSON+Padding的含义。)

jsonp是json用来跨域的一个东西。原理是通过script标签的跨域特性来绕过同源策略。

思考:这算怎么回事?

借助script标签,实现跨域请求,示例:

所以只是单纯的返回一个也没有什么意义,我们需要的是数据

如下:可以返回一个字典,不过也可以返回其他的(简单的解决了跨域,利用script)

项目一:


项目一

项目二:

def ajax_send2(request):
  import json
  print(222222)
  # return HttpResponse("func('name')")
  s = {"name":"haiyan","age":12}
  # return HttpResponse("func('name')")
  return HttpResponse("func('%s')"%json.dumps(s))  #返回一个func()字符串,正好自己的ajax里面有个func函数,就去执行func函数了,
                                arg就是传的形参

这样就会取到值了

这其实就是JSONP的简单实现模式,或者说是JSONP的原型:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。

将JSON数据填充进回调函数,这就是JSONP的JSON+Padding的含义。

但是以上的方式也有不足,回调函数的名字和返回的那个名字的一致。并且一般情况下,我们希望这个script标签能够动态的调用,而不是像上面因为固定在html里面所以没等页面显示就执行了,很不灵活。我们可以通过javascript动态的创建script标签,这样我们就可以灵活调用远程服务了。

解决办法:javascript动态的创建script标签

===========================jQuery实现=====================
{#  创建一个script标签,让他请求一次,请求完了删除他#}
  //动态生成一个script标签,直接可以定义个函数,放在函数里面
  function add_script(url) {
    var ele_script = $("



==================js实现==========================


为了更加灵活,现在将你自己在客户端定义的回调函数的函数名传送给服务端,服务端则会返回以你定义的回调函数名的方法,将获取的json数据传入这个方法完成回调:

function f(){
     addScriptTag("http://127.0.0.1:7766/SendAjax/?callbacks=func")
  }

将视图views改为

def SendAjax(request):
 
  import json
 
  dic={"k1":"v1"}
 
  print("callbacks:",request.GET.get("callbacks"))  
  callbacks=request.GET.get("callbacks")  #注意要在服务端得到回调函数名的名字
 
  return HttpResponse("%s('%s')"%(callbacks,json.dumps(dic)))

四、jQuery对JSONP的实现

getJSON

jQuery框架也当然支持JSONP,可以使用$.getJSON(url,[data],[callback])方法



8002的views不改动。

结果是一样的,要注意的是在url的后面必须添加一个callback参数,这样getJSON方法才会知道是用JSONP方式去访问服务,callback后面的那个?是内部自动生成的一个回调函数名。

此外,如果说我们想指定自己的回调函数名,或者说服务上规定了固定回调函数名该怎么办呢?我们可以使用$.ajax方法来实现

$.ajax

8002的views不改动。

当然,最简单的形式还是通过回调函数来处理:

jsonp: 'callbacks'就是定义一个存放回调函数的键,jsonpCallback是前端定义好的回调函数方法名'SayHi',server端接受callback键对应值后就可以在其中填充数据打包返回了;

jsonpCallback参数可以不定义,jquery会自动定义一个随机名发过去,那前端就得用回调函数来处理对应数据了。利用jQuery可以很方便的实现JSONP来进行跨域访问。  

注意 JSONP一定是GET请求

五、应用

// 跨域请求实例
  $(".jiangxiTV").click(function () {

    $.ajax({
      url:"http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403",
       dataType: 'jsonp',
       jsonp: 'callback',
       jsonpCallback: 'list',
       success:function (data) {
         console.log(data.data);  // [{},{},{},{},{},{}]
         week_list=data.data;
         
         $.each(week_list,function (i,j) {
           console.log(i,j); // 1 {week: "周一", list: Array(19)}
           s="

"+j.week+"列表

"; $(".show_list").append(s); $.each(j.list,function (k,v) { // {time: "0030", name: "通宵剧场六集连播", link: "http://www.jxntv.cn/live/jxtv2.shtml"} a="

"+v.name+"

"; $(".show_list").append(a); }) }) } }) })

相关推荐:

AJAX的常用语法是什么

几种javascript实现原生ajax的方法

jQuery一个ajax实例

The above is the detailed content of Detailed explanation of ajax and same origin strategy implemented by JS. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn