이번에는 네이티브 JS 비동기 요청으로 Ajax를 구현하는 방법을 보여드리겠습니다. Ajax를 구현하기 위한 네이티브 JS 비동기 요청에 대한 주의 사항은 무엇입니까?
프런트 엔드 페이지 개발 과정에서 Ajax 요청이 자주 사용되며 비동기적으로 양식 데이터를 제출하거나 페이지를 비동기적으로 새로 고칩니다.
일반적으로 Jquery에서 $.ajax,$.post,$.getJSON
를 사용하면 매우 편리하지만 때로는 Ajax 기능이 필요하다는 이유만으로 Jquery를 도입하는 것이 비용 효율적이지 않을 때도 있습니다.
다음으로, 기본 JavaScrpit을 사용하여 간단한 Ajax 요청을 구현하고, Ajax 요청의 도메인 간 액세스 문제와 여러 Ajax 요청의 데이터 동기화 문제를 설명하겠습니다.
JavaScript는 Ajax 비동기 요청을 구현합니다
간단한 Ajax 요청 구현
Ajax 요청의 원칙은 XMLHttpRequest 객체를 생성하고 이 객체를 사용하여 비동기적으로 요청을 보내는 것입니다. 구체적인 구현은 다음 코드를 참조하세요.
function ajax(option) { // 创建一个 XMLHttpRequest 对象 var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"), requestData = option.data, requestUrl = option.url, requestMethod = option.method; // 如果是GET请求,需要将option中的参数拼接到URL后面 if ('POST' != requestMethod && requestData) { var query_string = ''; // 遍历option.data对象,构建GET查询参数 for(var item in requestData) { query_string += item + '=' + requestData[item] + '&'; } // 注意这儿拼接的时候,需要判断是否已经有 ? requestUrl.indexOf('?') > -1 ? requestUrl = requestUrl + '&' + query_string : requestUrl = requestUrl + '?' + query_string; // GET 请求参数放在URL中,将requestData置为空 requestData = null; } // ajax 请求成功之后的回调函数 xhr.onreadystatechange = function () { // readyState=4表示接受响应完毕 if (xhr.readyState == ("number" == typeof XMLHttpRequest.DONE ? XMLHttpRequest.DONE : 4)) { if (200 == xhr.status) { // 判断状态码 var response = xhr.response || xhr.responseText || {}; // 获取返回值 // if define success callback, call it, if response is string, convert it to json objcet console.log(response); option.success && option.success(response); // 调用成功的回调函数处理返回值 // 可以判断返回数据类型,对数据进行JSON解析或者XML解析 // option.success && option.success('string' == typeof response ? JSON.parse(response) : response); } else { // if define error callback, call it option.error && option.error(xhr, xhr.statusText); } } }; // 发送ajax请求 xhr.open(requestMethod, requestUrl, true); // 请求超时的回调 xhr.ontimeout = function () { option.timeout && option.timeout(xhr, xhr.statusText); }; // 定义超时时间 xhr.timeout = option.timeout || 0; // 设置响应头部,这儿默认设置为json格式,可以定义为其他格式,修改头部即可 xhr.setRequestHeader && xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8'); xhr.withCredentials = (option.xhrFields || {}).withCredentials; // 这儿主要用于发送POST请求的数据 xhr.send(requestData); }
위 코드에는 자세한 설명이 있습니다. ajax의 원리는 일반적으로 XMLHttpRequest 객체를 사용하여 데이터를 보냅니다. 다음은 이 개체에 대한 보충 설명입니다.
많은 부울 표현식의 단락 속성은 조건문 작성을 대체하기 위해 코드에서 사용됩니다. 부울 표현식의 단락 속성을 잘 활용하면 수많은 간단한 조건문을 단순화할 수 있습니다. ^_^
XMLHttpRequest 객체의 기본 속성
ReadyState 속성에는 5개의 상태 값이 있습니다:
0: 초기화되지 않음: 초기화되지 않았습니다. XMLHttpRequest 객체가 생성되었지만 초기화되지 않았습니다.
1: 예 로드 중: 전송 준비가 완료되었습니다.
2: 로드됨,: 전송되었지만 아직 응답이 수신되지 않았습니다.
3: 대화형입니다. 응답이 수신되고 있지만 아직 수신되지 않았습니다.
4: 예 완료: 응답 수락이 완료되었습니다.
responseText: 서버가 반환한 응답 텍스트입니다. ReadyState>=3인 경우에만 값을 갖습니다. ReadyState=3인 경우 반환된 응답 텍스트가 불완전합니다. ReadyState=4인 경우에만 전체 응답 텍스트가 수신됩니다. responseXML: 응답 정보는 xml이며 Dom 객체로 구문 분석될 수 있습니다. 상태: 서버의 Http 상태 코드 200이면 OK, 404는 찾을 수 없음을 의미합니다. statusText: 서버 http 상태 코드의 텍스트입니다. 예를 들어 확인, 찾을 수 없음입니다.
XMLHttpRequest 객체의 기본 메서드
open(method, url, asyn): XMLHttpRequest 객체를 엽니다. 메소드에는 get, post, delete 및 put이 포함됩니다. url은 요청된 리소스의 주소입니다. 세 번째 매개변수는 비동기식 사용 여부를 나타냅니다. Ajax의 특성은 비동기 전송이기 때문에 기본값은 true입니다. 동기화가 사용되는 경우 거짓입니다. send(body): 요청 Ajax를 보냅니다. 전송되는 내용은 필수 매개변수일 수 있습니다. 매개변수가 없으면 (null)을 직접 전송하세요
사용방법
위에 정의된 ajax 함수를 호출하고 해당 옵션과 매개변수를 전달하면 됩니다.
rreee교차 도메인 요청 문제
Ajax 요청을 사용할 때 한 가지 문제, 즉 도메인 간 요청에 주의해야 합니다. 특별한 수단을 사용하지 않고 크로스 도메인 요청: 다른 도메인 이름 및 포트로 URL 리소스를 요청할 경우 오류 메시지가 보고됩니다. Access-Control-Allow-Origin 관련 오류. 주된 이유는 크로스 도메인 리소스 요청이 이루어질 수 없도록 규정하는 브라우저의 동일 출처 정책 제한 때문입니다.
솔루션
다음은 간략하게 언급된 몇 가지 솔루션입니다. ajax 헤더에 도메인 간 요청을 허용하는 헤더를 추가하려면 서버가 도메인 간 요청을 허용하는 헤더 추가에 협력해야 합니다. 다음은 POST 요청에 Allow cross-domain 헤더를 추가하는 PHP 예제입니다.
ajax({ url: '/post.php', data: { name: 'uusama', desc: 'smart' }, method: 'GET', success: function(ret) { console.log(ret); } });
동적 scrpit 태그를 사용하여 scrpit 태그를 동적으로 생성하고 요청한 주소를 가리키는 방식, 즉 JSONP 방식에서는 태그가 성공적으로 로드된 후 콜백 함수가 호출됩니다.
rreee콜백 함수는 전역 함수로 설정되어야 합니다:
// 指定允许其他域名访问 header('Access-Control-Allow-Origin:*'); // 响应类型 header('Access-Control-Allow-Methods:POST'); // 响应头设置 header('Access-Control-Allow-Headers:x-requested-with,content-type');
여러 Ajax 요청으로 인한 데이터 동기화 문제
단일 Ajax 반환 데이터의 비동기 처리
多个ajax请求互不相关,它们在被调用以后发送各自请求,请求成功以后调用自己的回调方法,互不影响。 因为ajax请求异步的特性,所有一些依赖于请求完成之后的操作我们都需要放在回调函数内部,否则的话,你在回调函数外面读取到的值是空。看下面的例子:
var result = null; ajax({ url: '/get.php?id=1', method: 'GET', success: function(ret) { result = ret; } }); console.log(result); // 输出 null
虽然我们在回调函数里面设置了result的值,但是在最后一行 console.log(result); 输出为空。 因为ajax请求是异步的,程序执行到最后一行的时候,请求并没有完成,值并没有来得及修改。 这儿我们应该把 console.log(result) 相关的处理,放在 success 回调函数中才可以。
多个ajax返回数据问题
如果有多个ajax请求,情况会变得有些复杂。 如果多个ajax请求是按照顺序执行的,其中一个完成之后,才能进行下一个,则可以把后面一个请求放在前一后请求的回调中。 比如有两个ajax请求,其中一个请求的数据依赖于另外一个,则可以在第一个请求的回调里面再进行ajax请求:
// 首先请求第一个ajax ajax({ url: '/get1.php?id=1', success: function(ret1) { // 第一个请求成功回调以后,再请求第二个 if (ret1) { ajax({ url: '/get2.php?id=4', success:function(ret2) { console.log(ret1); console.log(ret2) } }) } } }); // 也可以写成下面的形式 var ajax2 = function(ret1) { ajax({ url: '/get2.php?id=4', success:function(ret2) { console.log(ret1); console.log(ret2) } }); }; ajax({ url: '/get1.php?id=1', success: function(ret1) { if(ret1){ ajax2(ret1); } } });
如果不关心不同的ajax请求的顺序,而只是关心所有请求都完成,才能进行下一步。 一种方法是可以在每个请求完成以后都调用同一个回调函数,只有次数减少到0才执行下一步。
var count = 3, all_ret = []; // 调用3次 ajax({ url: '/get1.php?id=1', success:function(ret) { callback(ret); } }); ajax({ url: '/get2.php?id=1', success:function(ret) { callback(ret); } }); ajax({ url: '/get3.php?id=1', success:function(ret) { callback(ret); } }); function callback(ret) { if (count > 0) { count--; // 可以在这儿保存 ret 到全局变量 all_ret.push(ret); return; } else { // 调用三次以后 // todo console.log(ret); } }
另一种方法是设置一个定时任务去轮训是否所有ajax请求都完成,需要在每个ajax的成功回调中去设置一个标志。 这儿可以用是否获得值来判断,也可以设置标签来判断,用值来判断时,要注意设置的值和初始相同的情况。
var all_ret = { ret1: null, // 第一个ajax请求标识 ret2: null, // 第二个ajax请求标识 ret3: null, // 第三个ajax请求标识 }; ajax({ url: '/get1.php?id=1', success:function(ret) { all_ret['ret1'] = ret; // 设置第一个ajax请求完成,把结果更新 } }); ajax({ url: '/get2.php?id=1', success:function(ret) { all_ret['ret2'] = ret; // 设置第二个ajax请求完成,把结果更新 } }); ajax({ url: '/get3.php?id=1', success:function(ret) { all_ret['ret3'] = ret; // 设置第三个ajax请求完成,把结果更新 } }); var repeat = setInterval(function(){ // 循环检查是否所有设置的ajax请求结果的值是否都已被更改,都已被更改说明所有ajax请求都已完成 for(var item in all_ret) { if (all_ret[item] === null){ return; } } // todo, 到这儿所有ajax请求均已完成 clearInterval(repeat); }, 50);
PS:下面看下ajax异步请求实例代码,具体代码如下所示:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>获得书籍列表</title> <script type="text/javascript"> var xmlhttp; var txt,x,xx,i; function loadXMLDoc(url,cfunc) { if(window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp = new XMLHttpRequest(); } else { // code for IE6, IE5 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange = cfunc; xmlhttp.open("GET", "<%=request.getContextPath()%>"+url, true); xmlhttp.send(); } function myFunction1() { loadXMLDoc("/xmls/books.xml",function(){ if(xmlhttp.readyState==4 && xmlhttp.status==200) { var xmlDoc = xmlhttp.responseXML; txt = ""; x = xmlDoc.getElementsByTagName_r("title"); for(i=0;i<x.length;i++) { txt = txt + x[i].childNodes[0].nodeValue+"<br/>"; } document.getElementByIdx_x("myp").innerHTML = txt; } }); } function myFunction2() { loadXMLDoc("/text/test1.txt",function(){ if(xmlhttp.readyState==4 && xmlhttp.status==200) { document.getElementByIdx_x("myp").innerHTML = xmlhttp.responseText; } }); } function myFunction3() { loadXMLDoc("/xmls/cd_catalog.xml",function(){ if(xmlhttp.readyState==4 && xmlhttp.status==200) { txt="<table border='1'><tr><th>Title</th><th>Artist</th></tr>" x= xmlhttp.responseXML.documentElement.getElementsByTagName_r("CD"); for(i=0;i<x.length;i++) { txt = txt + "<tr>"; xx = x[i].getElementsByTagName_r("TITLE"); { try{ txt = txt + "<td>" + xx[0].firstChild.nodeValue +"</td>"; } catch(er) { txt = txt +"<td></td>"; } xx = x[i].getElementsByTagName_r("ARTIST"); try { txt = txt + "<td>" + xx[0].firstChild.nodeValue +"</td>"; } catch(er) { txt = txt + "<td></td>"; } } txt = txt + "</tr>" } txt = txt + "</table>"; document.getElementByIdx_x("myp").innerHTML =txt; } }); } </script> </head> <body> <h2>My Book Collection:</h2> <button type="button" onClick="myFunction1()">获得我的图书收藏列表</button> <button type="button" onClick="myFunction2()">这是不同的请求</button> <button type="button" onClick="myFunction3()">获取CD信息</button> <p id="myp"></p> </body> </html>
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
위 내용은 네이티브 JS에서 비동기 요청으로 Ajax를 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!