이번에는 네이티브 JS에서 Ajax 비동기를 구현하는 몇 가지 방법과 네이티브 JS에서 Ajax 비동기를 구현하는 노트를 소개하겠습니다.
프런트 엔드 페이지 개발 과정에서 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콜백 함수는 global function:
으로 설정되어야 합니다.
window['jsonpCallback'] = function jsonpCallback(ret) {}
다중 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) } }) } } }); // 也可以写成下面的形式 // 将第二个ajax请求定义为一个函数,然后调用 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请求 } } });
如果不关心不同的ajax请求的顺序,而只是关心所有请求都完成,才能进行下一步。
一种方法是可以在每个请求完成以后都调用同一个回调函数,只有次数减少到0才执行下一步。
var count = 3, all_ret = []; // 调用3次 ajax({ url: '/get1.php?id=1', success:function(ret) { callback(ret); // 请求成功后调用统一回调,次数减1 } }); 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) { // 当调用3次以上以后,说明3个ajax军完成 if (count > 0) { count--; // 每调用一次,次数减1 // 可以在这儿保存 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); // 调用次数可以适当调整,不应设的过小或者过大
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
在IE11下里使用canvas.toDataURL兼容性问题的解决思路
위 내용은 기본 JS에서 Ajax를 비동기식으로 구현하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!