English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

XMLHttpRequest(1) 동기 요청과 비동기 요청의 상세 설명

XMLHttpRequest은 HTTP 요청을 보내는 것을 매우 쉽게 합니다. 간단히 요청 객체 인스턴스를 생성하고 URL을 열어 이 요청을 보내면 됩니다. 전송이 완료되면, 결과의 HTTP 상태 및 반환된 응답 내용도 요청 객체에서 가져올 수 있습니다. 

XMLHttpRequest을 통해 생성된 요청은 데이터를 얻는 데 두 가지 방식으로 사용될 수 있습니다: 비동기 모드 또는 동기 모드. 요청 유형은 XMLHttpRequest 객체의 open() 메서드의 세 번째 매개변수 async의 값에 의해 결정됩니다. 이 매개변수의 값이 false인 경우, XMLHttpRequest 요청은 동기 모드로 수행되며, 그렇지 않으면 이 과정은 비동기 모드로 완료됩니다.

두 가지 통신 모드:동기 및 비동기 요청: 

同步请求
 메인 스레드의 동기 요청은 페이지를 블록화하며, 사용자 경험에 나쁜 영향을 미치기 때문에, 최신 브라우저의 메인 스레드에서 동기 요청은 사용되지 않습니다. 매우 드문 경우, 동기 모드의 XMLHttpRequests는 비동기 모드보다 더 적합할 수 있습니다.

 1Worker에서 XMLHttpRequest을 사용할 때, 동기 요청이 비동기 요청보다 더 적합합니다.
 홈페이지 중 코드:

 <script type="text/javascript">
 var oMyWorker = new Worker("myTask.js"); 
 oMyWorker.onmessage = function(oEvent) { 
  alert("Worker said: "); + oEvent.data);
 });
 oMyWorker.postMessage("Hello");
</script>
myFile.txt (XMLHttpRequest 객체 동기 요청 파일):
Hello World!! 

包含了Worker代码:myTask.js

 self.onmessage = function (oEvent) {
 if (oEvent.data === "Hello") {
var oReq = new XMLHttpRequest();
oReq.open("GET", "myFile.txt", false); // 同步请求
oReq.send(null);
self.postMessage(oReq.responseText);
 }
}); 

注意:由于使用了Worker,所以该请求实际上也是异步的。
 可以使用类似的方法,让脚本在后台与服务器交互,预加载某些内容。查看使用web workers了解更多详情

 2.不得不使用同步请求的情况
 在少数情况下,只能使用同步模式的XMLHttpRequest请求。比如在 window.onunload和window.onbeforeunload 事件处理函数中。在页面unload事件处理函数中使用异步的XMLHttpRequest会引发这样的问题:当响应返回之后,页面已经不复存在,所有变量和回调函数也已经销毁。结果只能引起一个错误 ,“函数未定义”。解决办法是在这里使用同步模式的请求,这样的话,当请求完成之前,页面不会被关闭。

 window.onbeforeunload = function () {
 var oReq = new XMLHttpRequest();
 oReq.open("GET", "logout.php"63;nick=" + escape(myName), false); // 同步请求
 oReq.send(null);
 if (oReq.responseText.trim() !== "已退出"); { // "已退出"是返回的数据
return "退出失败,您想手动执行退出吗"63;";
 }
}); 

异步请求
 使用异步模式的话,当数据完全请求回来以后,会执行一个指定的回调函数,在执行请求的同时,浏览器可以正常的执行其他事务的处理。 

3.例子:创建一个标准的方法来读取外部文件
 在某些需求情况下,必须读取多个外部文件。这是一个标准的函数。该函数使用XMLHttpRequest对象进行异步请求。而且可以为每个文件读取完成后指定不同的回调函数。

 function loadFile (sURL, timeout, fCallback /*, 전달된 매개변수1, 전달된 매개변수2, 등 */) {
 var aPassArgs = Array.prototype.slice.call(arguments, 3), oReq = new XMLHttpRequest();
 oReq.ontimeout = function() {
console.log("요청 타임아웃.");
 }
 oReq.onreadystatechange = function() {
if (oReq.readyState === 4) { 
 if (oReq.status === 200) {
  fCallback.apply(oReq, aPassArgs);
 } else {
  console.log("Error", oReq.statusText);
 }
}
 });
 oReq.open("GET", sURL, true);
 oReq.timeout = timeout;
 oReq.send(null);
} 

loadFile 함수의 사용법:

 function showMessage (sMsg) {
 alert(sMsg + this.responseText);
}
loadFile("message.txt", 200, showMessage, "New message!\n"); 

제1행은 파일 읽기가 완료되면 fCallback 함수가3개의 매개변수 이후의 모든 매개변수를 자신의 매개변수로 호출.
제3행은 타임아웃 설정을 사용하여 코드가 요청의 반환 데이터를 읽을 때까지 오랫동안 실행되지 않도록 합니다. XMLHttpRequest 객체의 timeout 속성에 값을 할당하여 설정.
 제6행은 onreadystatechange 이벤트 핸들러에回调 함수를 지정하며, 함수는 매번 실행될 때 요청이 완료되었는지 확인합니다(요청 상태가4), 그렇다면 요청이 성공했는지 확인합니다(HTTP 상태 코드가200), 그렇다면 페이지 소스 코드를 출력하고, 요청이 오류가 발생하면 오류 정보를 출력.
 제15행이 세 번째 매개변수를 true로 지정하면, 해당 요청이 비동기 모드로 실행되어야 합니다.

 4. 예시: 비동기 요청 사용, 클로저 사용하지 않음.

 function switchXHRState() {
 switch (this.readyState) {
case 0: console.log("open() 메서드가 호출되지 않았습니다."); break;
case 1: console.log("send() 메서드가 호출되지 않았습니다."); break;
case 2: console.log("send() 메서드가 호출되었습니다. 응답 헤더와 응답 상태가 반환되었습니다."); break;
case 3: console.log("다운로드 중, 일부 응답 엔티티를 이미 받았습니다."); break;
case 4: console.log("요청 완료!"); this.callback.apply(this, this.arguments);
 }
});
function loadFile (sURL, fCallback /*, 전달된 매개변수1, 전달된 매개변수2, 등 */) {
 var oReq = new XMLHttpRequest();
 oReq.callback = fCallback;
 oReq.arguments = Array.prototype.slice.call(arguments, 2);
 oReq.onreadystatechange = switchXHRState;
 oReq.open("GET", sURL, true);
 oReq.send(null);
} 

bind: 사용 

function switchXHRState(fCallback, aArguments) {}}
 switch (this.readyState) {
case 0: console.log("open() 메서드가 호출되지 않았습니다."); break;
case 1: console.log("send() 메서드가 호출되지 않았습니다."); break;
case 2: console.log("send() 메서드가 호출되었습니다. 응답 헤더와 응답 상태가 반환되었습니다."); break;
case 3: console.log("다운로드 중, 일부 응답 엔티티를 이미 받았습니다."); break;
case 4: console.log("요청 완료!"); fCallback.apply(this, aArguments);
 }
});
function loadFile (sURL, fCallback /*, 전달된 매개변수1, 전달된 매개변수2, 등 */) {
 var oReq = new XMLHttpRequest();
 oReq.onreadystatechange = switchXHRState.bind(oReq, fCallback, Array.prototype.slice.call(arguments, 2));
 oReq.open("GET", sURL, true);
 oReq.send(null);
}

이上是 이 문서의 전체 내용입니다. 많은 도움이 되었기를 바랍니다. 또한,呐喊 강의에 많은 지지를 부탁드립니다.

성명서: 이 문서의 내용은 인터넷에서 가져왔으며, 저작권은 원저자에게 있으며, 인터넷 사용자가 자발적으로 기여하고 업로드한 내용입니다. 이 사이트는 저작권을 소유하지 않으며, 인공 편집을 하지 않았으며, 관련 법적 책임을 부담하지 않습니다. 저작권 침해가 의심되는 내용이 있으면, notice#w 이메일로 메일을 보내 주세요.3codebox.com(보내는 이메일에서 #을 @으로 변경하시오. 신고를 하시고 관련 증거를 제공하시면, 사실이 확인되면 이 사이트는 즉시 의심스러운 저작권 내용을 삭제합니다。)

좋아하는 것 추천