Ajax는 최신 웹 애플리케이션 개발의 핵심 도구입니다. 서버에 비동기 적으로 데이터를 보내고 수신 한 다음 JavaScript로 구문 분석 할 수 있습니다. Ajax는 비동기 JavaScript 및 XML (비동기 JavaScript 및 XML)의 약어입니다.
Ajax 코어 사양의 이름은 요청을 작성하고 시작하는 데 사용되는 JavaScript 객체에서 상속됩니다 : xmlhttprequest. 이 사양에는 두 가지 수준이 있습니다. 모든 주류 브라우저는 기본 기능 수준을 나타내는 첫 번째 레벨을 구현합니다. 두 번째 레벨은 초기 사양을 확장하고 추가 이벤트 및 일부 기능을 통합하여 양식 요소와 쉽게 협업 할 수 있으며 일부 관련 사양을 지원합니다.
1. Ajax가 시작됩니다
Ajax의 핵심은 xmlhttprequest 객체에 있으며이 개체를 이해하는 방법은 예를 보는 것입니다. 다음 코드는 xmlhttprequest 객체의 간단한 사용을 보여줍니다.
<! docType html> <html lang = "en"> <head> <meta charset = "utf-8"> <title> 예 </title> </head> <body> <div> <버튼> 사과> <버튼> cherries </button> <button> </div> <div id = "target"> scr </div "> type = "application/javaScript"> var buttons = document.getElementsByTagName ( "버튼"); for (var i = 0; i <buttons.length; i ++) {버튼 [i] .onclick = handleButtonpress; } // 스크립트는이 기능을 호출하여 버튼 컨트롤의 클릭 이벤트 기능 handlebuttonpress (e)에 응답합니다. {// 새 xmlhttprequest 개체 var httprequest = new xmlhttprequest (); // OnreadyStateChange 이벤트 httprequest.onreadyStateChange = handlerPonse; // 열린 메소드를 사용하여 http 메소드와 URL을 지정하여 요청할 URL을 지정하십시오 (즉, httprequest 객체에 원하는 대상을 알려주십시오) httprequest.open ( "get", e.target.innerhtml+". html"); // 여기에서 서버로 전송되지 않으므로 보내기 메소드에는 사용 가능한 매개 변수가 없습니다 httpRequest.send (); } // 응답 처리 // 스크립트가 Send 메소드를 호출하면 브라우저가 백그라운드에서 서버에 요청을 보냅니다. 요청이 백그라운드에서 처리되므로 Ajax는 이벤트에 의존하여 요청의 진행 상황을 알립니다. 함수 handlerSponse (e) {// onreadyStateChange 이벤트가 트리거되면 브라우저는 이벤트 객체를 지정된 핸들러 기능으로 전달하고 대상 속성은이 이벤트와 관련된 XMLHTTPREQUEST로 설정됩니다. document.getElementById ( "target"). innerhtml = e.target.responsetext; // 요청 된 문서의 내용을 표시}} </script> </body> </html>세 가지 추가 문서는 매우 간단합니다.
<! doctype html> <html lang = "en"> <head> <meta charset = "utf-8"> <title> 사과 </title> <style> img {float : 왼쪽; 패딩 : 2px; 마진 : 5px; 경계 : 중간 더블 블랙; 배경 색 : Lightgrey; 너비 : 100px; 높이 : 100px;} </style> </head> <body> <p> <img src = "../ 사과의 경우 img/show-page/img_apples.jpg"/> 페이지. </p> </body> </html>효과는 아래 그림에 나와 있습니다.
사용자가 각 과일 버튼을 클릭하면 브라우저가 비동기식으로 실행되고 요청 된 문서를 검색하는 반면 기본 문서는 다시로드되지 않습니다. 이것은 전형적인 ajax 동작입니다.
2. Ajax 이벤트 사용
간단한 예제를 작성하고 탐색 한 후 XMLHTTPREQUEST 객체가 지원하는 기능과 요청에서이를 사용하는 방법을 파헤 치기 시작할 수 있습니다. 시작점은 두 번째 레벨 사양에 정의 된 추가 이벤트입니다.
이러한 이벤트의 대부분은 요청 중 특정 시점에서 트리거됩니다. 두 이벤트는 예외, ReadyStateChange 및 진행 상황이며 진행 상황 업데이트를 제공하기 위해 여러 번 트리거 될 수 있습니다.
이러한 이벤트가 예약되면 브라우저는 ReadyStateChange 이벤트에 정기적 인 이벤트 객체와 다른 이벤트의 진행 상황을 사용합니다. ProgressEvent 객체는 이벤트 객체의 모든 멤버를 정의하고 다음 그림에 설명 된이 멤버를 추가합니다.
다음 코드는 이러한 이벤트 사용 방법을 보여줍니다.
<! doctype html> <html lang = "en"> <head> <meta charset = "utf-8"> <title> 예 </title> <style> 테이블 {margin : 10px; Border-Collapse : 붕괴; float : 왼쪽;} div {margin : 10px;} td, th {padding : 4px;} </style> </head> <div> <div> <div> </button> <butty> 체리> </button> </button> bananas </div> <table id = "events "> <div id ="target a </div> <div id = "target"> type = "application/javaScript"> var buttons = document.getElementsByTagName ( "버튼"); for (var i = 0; i <buttons.length; i ++) {버튼 [i] .onclick = handleButtonpress; } var httpRequest; 함수 handleButtonpress (e) {clareEventDetails (); httprequest = new xmlhttprequest (); httprequest.onreadyStateChange = handlerPonse; httprequest.onerror = handleerRor; httprequest.onload = handleload ;; httprequest.onloadend = handleloadend; httprequest.onloadstart = handleloadstart ;; httprequest.onprogress = handleprogress; httprequest.open ( "get", e.target.innerhtml+". html"); httprequest.send (); } function handlerSponse (e) {displayEventDetails ( "readystate ("+httprequest.readystate+")") if (e.target.readystate == xmlhttprequest.done && e.target.status == 200) {target.getErml.getEtletteT (e.getErml); }} 함수 handleError (e) {displayEventDetails ( "error", e);} 함수 handleload (e) {displayEventDetails ( "load", e);} 함수 handleloadend (e) {displayEventDetails ( "loadend", e); e) {e) {e) {e) { handleloadstart (e) {displayEventDetails ( "loadStart", e);} 함수 handleProgress (e) {displayEventDetails ( "progress", e);} 함수 clearEventDetails () {document.getElementById ( "events"). innerHtml = "<tr> <th> 이벤트 </th> <th> Length Computable </th> <th>로드 </th> <th> 총 </th>"; } function displayEventDetails (eventName, e) {if (e) {docum e.total+"</td> </tr>"; } else {document.getElementById ( "events"). innerHtml+= "<tr> <td>"+eventName+"</td> <td> na </td> <td> na </td> <td> na </td> <td> na </td>"; }} </script> </body> </html>이것은 이전 예제의 변형으로, 일부 이벤트에 대한 핸들러를 등록하고 테이블 요소에서 처리 된 각 이벤트에 대한 레코드를 작성합니다. 다음 이미지에서 Firefox 브라우저가 어떻게 이러한 이벤트를 트리거하는지 확인할 수 있습니다.
3. 핸들 오류
Ajax를 사용할 때 두 가지 유형의 오류가주의를 기울여야합니다. 그것들의 차이는 다른 관점에서 비롯됩니다.
첫 번째 유형의 오류는 xmlhttprequest 객체의 관점에서 볼 수있는 문제입니다. 일부 요인으로 인해 요청이 서버로 전송되는 것을 방지합니다. 예를 들어, DNS는 호스트 이름을 해결할 수 없거나 연결 요청이 거부되거나 URL이 유효하지 않습니다.
두 번째 유형의 문제는 xmlhttprequest 객체가 아닌 응용 프로그램 관점에서 볼 수있는 문제입니다. 요청이 서버로 성공적으로 전송 될 때 발생하여 요청을 수신하고 처리하고 응답을 생성하지만 응답은 귀하가 기대하는 것을 가리키지 않습니다. 예를 들어, 요청 된 URL이 존재하지 않으면 이러한 종류의 문제가 발생합니다.
다음 코드와 같이 이러한 오류를 처리하는 세 가지 방법이 있습니다.
3.1 설정 오류 처리
처리 해야하는 첫 번째 유형의 문제는 잘못된 데이터를 잘못된 URL과 같은 XMLHTTPRESQUEST 객체에 전달하는 것입니다. 사용자 입력을 기반으로 URL을 생성 할 때 발생하기 쉽습니다. 이러한 종류의 문제를 시뮬레이션하기 위해 위의 문서에는 태그 불량 URL (잘못된 URL)을 추가하는 버튼이 있습니다. 이 버튼을 누르면 열린 메소드를 다음 형식으로 호출합니다.
httprequest.open ( "get", "http : //")
이것은 요청이 실행되는 것을 방지하는 오류이며, 이와 같은 이벤트가 xmlhttprequest 객체에서 발생할 때 오류가 발생합니다. 즉, 시도를 설정하는 코드를 둘러싸고 다음과 같이 시도해 보는 시도가 필요하다는 것을 의미합니다.
try {... httprequest.open ( "get", "http : //") ... httprequest.send (); } catch (error) {displayerRormsg ( "try/catch", error.message)}Catch 절은 오류에서 복구 할 수있는 기회를 제공합니다. 값을 사용자에게 프롬프트하거나 기본 URL로 돌아가거나 간단히 요청을 폐기하도록 선택할 수 있습니다. 이 예에서는 DisplayERrormsg 함수가 호출되어 오류 메시지를 표시합니다.
3.2 처리 요청 오류
두 번째 유형의 오류는 요청이 생성되었을 때 발생하지만 다른 오류가 있습니다. 이러한 유형의 문제를 시뮬레이션하기 위해 예제에 BAD 호스트 (오류 호스트)라는 버튼이 추가되었습니다. 이 버튼을 누르면 열린 메소드가 호출되어 사용할 수없는 URL에 액세스합니다.
httprequest.open ( "get", http : //www.ycdoitt.com/nopage.html)
이 URL에는 두 가지 문제가 있습니다. 첫 번째 문제는 DNS에서 호스트 이름을 해결할 수 없으므로 브라우저가 서버 연결을 생성 할 수 없다는 것입니다. 이 문제는 xmlhttprequest 객체가 요청을 생성하기 시작할 때만 분명해 지므로 두 가지 방식으로 오류를 표시합니다. 오류 이벤트에 대한 리스너를 등록하면 브라우저는 이벤트 객체를 리스너에게 보냅니다. 예제에 사용 된 기능은 다음과 같습니다.
함수 handleError (e) {displayerRormsg ( "오류 이벤트", httpRequest.status + httprequest.statustext); }이러한 오류가 발생하면 XMLHTTPREQUEST 객체에서 얻을 수있는 정보의 정도는 브라우저에 따라 다릅니다. 불행히도 대부분의 경우 값이 0이고 빈 통계 텍스트 값이있는 상태가 얻어집니다.
두 번째 문제는 URL과 생성 된 요청에 다른 소스가 있으며 기본적으로 허용되지 않는다는 것입니다. 일반적으로 스크립트를로드하는 동일한 오리핀 URL에 AJAX 요청 만 보낼 수 있습니다. 브라우저 가이 문제를보고하면 오류가 발생하거나 오류 이벤트가 트리거 될 수 있습니다. 다른 브라우저는 다르게 처리합니다. 다른 브라우저는 또한 다른 시점에서 소스를 확인하므로 브라우저가 항상 동일한 문제를 강조하는 것은 아닙니다. 크로스 오리핀 자원 공유는 상 동성 제한을 우회하는 데 사용될 수 있습니다.
3.3 응용 프로그램 오류 처리
마지막 유형의 오류는 요청이 성공적으로 완료 될 때 (XMLHTTPREQUEST 객체의 관점에서) 원하는 데이터를 반환하지 않습니다. 이러한 문제를 만들려면 위의 예에 레이블 오이가있는 버튼을 추가하십시오. 이 버튼을 누르면 사과, 체리 및 바나나 버튼과 유사한 요청 URL이 생성되지만 Cucumber.html 문서는 서버에 없습니다.
이 프로세스 자체에는 오류가 없으며 (요청이 완료 되었기 때문에) 상태 속성에 따라 무슨 일이 일어나고 있는지 결정해야합니다. 기존 문서를 요청하면 상태 코드 404가 얻어 지므로 서버가 요청 된 문서를 찾을 수 없습니다. 예제가 200 이외의 다른 상태 코드를 처리하는 방법을 볼 수 있습니다 (확인).
if (httprequest.status == 200) {target.innerhtml = httprequest.responsetext; } else {document.getElementById ( "statusMSG"). innerHtml = "상태 :" + httpRequest.status + "" + httprequest.statUStext; }이 예에서는 상태와 Statustext의 값이 간단하게 표시됩니다. 실제 응용 프로그램에서 복구는 유용하고 의미있는 방식으로 수행되어야합니다 (예 : 응용 프로그램에 더 적합한 사람에 따라 대체 콘텐츠 표시 또는 경고 사용자).
4. 헤더를 얻고 설정하십시오
xmlhttprequest 객체를 사용하면 서버로 전송 된 요청 헤더와 서버 응답에서 헤더를 설정할 수 있습니다.
4.1 요청에 대한 HTTP 방법을 덮어 씁니다
일반적으로 AJAX 요청에서 헤더를 추가하거나 수정할 필요는 없습니다. 브라우저는 보내야 할 사항을 알고 있으며 서버는 응답 방법을 알고 있습니다. 그러나 몇 가지 예외가 있습니다. 첫 번째는 x-http-method-override 헤더입니다.
HTTP 표준은 종종 인터넷에서 HTML 문서를 요청하고 전송하는 데 사용되며 많은 방법을 정의합니다. 대부분의 사람들은 가장 널리 사용되기 때문에 Get and Post에 대해 알고 있습니다. 그러나 서버에 요청 된 URL에 의미를 부여하는 데 사용되는 다른 방법 (Put and Delete 포함)이 있으며이 사용법은 증가하고 있습니다. 예를 들어, 사용자 레코드를 보려면 그러한 요청을 생성 할 수 있습니다.
httprequest.open ( "get", "http : // myserver/records/freeman/adam");
HTTP 방법과 요청 된 URL 만 여기에 표시됩니다. 이 요청이 원활하게 작동하려면 서버 측은 응용 프로그램의 요청을 이해하고 서버로 다시 전송 될 적절한 데이터로 변환 할 수 있어야합니다. 데이터를 삭제하려면 다음과 같이 쓸 수 있습니다.
httprequest.open ( " delete ", "http : // myserver/records/freeman/adam");
여기서 핵심은 서버가 HTTP를 통해 수행하려는 작업을 어떤 식 으로든 URL에 인코딩하는 대신 원하는 것을 표현하는 것입니다.
이러한 방식으로 HTTP 방법을 사용하는 데있어 문제는 많은 주류 웹 기술이 Get and Post 만 지원하며 많은 방화벽은 Get and Post 요청 만 통과 할 수 있다는 것입니다. 이 제한을 피하기위한 관용적 접근법이 있습니다.이 제한은 x-http-method-override 헤더를 사용하여 사용하려는 HTTP 메소드를 지정하는 것이지만 양식이 마케팅되어 게시물 요청을 보냅니다. 코드 데모는 다음과 같습니다.
<! docType html> <html lang = "en"> <head> <meta charset = "utf-8"> <title> 예 </title> </head> <body> <div> <butty> apples </button> <button> cherries </button> <button> bananas </div id = "target"> button </div> <scr. document.getElementsByTagName ( "버튼"); for (var i = 0; i <buttons.length; i ++) {버튼 [i] .onclick = handleButtonpress; } var httpRequest; 함수 handleButtonpress (e) {httpRequest = new xmlhttprequest (); httprequest.onreadyStateChange = handlerPonse; httprequest.open ( "get", e.target.innerhtml+". html"); httprequest.setrequestheader ( "x-http-method-override", "delete"); httprequest.send (); } function handleError (e) {displayErrormsg ( "오류 이벤트", httpRequest.status+httprequest.statustext); } function handlerSponse () {if (httprequest.readystate == 4 && httprequest.status == 200) {document.getElementById ( "target"). innerHtml = httpRequest.ResponSetext; }} </script> </body> </html>이 예에서 XMLHTTPREQUEST 객체의 setRequestHeader 메소드는 요청이 HTTP 삭제 방법의 형태로 처리되기를 원한다는 것을 나타냅니다. 열린 메소드를 호출 한 후에만이 헤더를 설정합니다. 열린 메소드 전에 setRequestheader 메소드를 사용하려고하면 xmlhttprequest 객체가 오류를 던집니다.
PS : HTTP를 덮어 쓰기 위해서는 서버 측 웹 애플리케이션 프레임 워크가 X-HTTP-Method-Override의 규칙을 이해하도록 요구하며, 서버 측 응용 프로그램은 덜 HTTP 방법을 찾고 이해하도록 설정해야합니다.
4.2 컨텐츠 캐싱 비활성화
AJAX 요청에 추가 할 수있는 두 번째 유용한 헤더는 캐시 제어이며 스크립트를 작성하고 디버깅 할 때 특히 유용합니다. 일부 브라우저는 AJAX 요청을 통해 얻은 콘텐츠를 캐시하며 브라우징 세션 중에 다시 요청하지 않습니다. 이전 예제에서는 사과의 변경, cherries.html 및 bananas.html의 변경이 브라우저에 즉시 반영되지 않음을 의미합니다. 다음 코드는이를 피하기 위해 헤더를 설정하는 방법을 보여줍니다.
httprequest = new xmlhttprequest (); httprequest.onreadyStateChange = handlerPonse; httprequest.open ( "get", e.target.innerhtml+". html"); httprequest.setRequestHeader ( "캐시 제어", "없음"); httprequest.send ();
헤더를 설정하는 방법은 이전 예제에서와 동일하지만 이번에는 헤더가 캐시 제어이며 원하는 값은 캐시가 없습니다. 이 명령문을 작성한 후 AJAX를 통해 요청 된 내용이 변경되면 다음에 문서가 요청 될 때 반영됩니다.
4.3 응답 헤더를 읽으십시오
AJAX 요청에 응답 할 때 서버가 전송 한 HTTP 헤더는 getREpponseHeader 및 getAllResponseHeaders 메소드를 통해 읽을 수 있습니다. 대부분의 경우 브라우저와 서버 간의 대화식 트랜잭션의 일부이기 때문에 헤더의 내용에 대해 신경 쓰지 않아도됩니다. 다음 코드는이 속성을 사용하는 방법을 보여줍니다.
<! docType html> <html lang = "en"> <head> <meta charset = "utf-8"> <meta content = "width = device-width, user-scalable = no"noverport " /> <meta name ="author "컨텐츠 ="ye chaoluka "/> <meta name ="desction ""simple eximal " href = "../ img/ycdoit.ico"type = "im <버튼> 바나나 </button> </div> <div id = "cheader"> </div> <div id = "AllHeaders"> </div> <div id = "target"> 버튼 </div> <cript> var buttons = document.getElementsByTagName ( "버튼"); for (var i = 0; i <buttons.length; i ++) {버튼 [i] .onclick = handleButtonpress; } var httpRequest; 함수 handleButtonpress (e) {httpRequest = new xmlhttprequest (); httprequest.onreadyStateChange = handlerPonse; httprequest.open ( "get", e.target.innerhtml+". html"); httprequest.setRequestHeader ( "캐시 제어", "없음"); httprequest.send (); } function handlerSponse () {if (httprequest.readystate == 2) {document.getElementById ( "AllHeaders"). innerHtml = httpRequest.getallResponseHeaders (); documb } else if (httpRequest.readystate == 4 && httprequest.status == 200) {document.getElementById ( "target"). innerHtml = httprequest.responsetext; }} </script> </body> </html>렌더링은 다음과 같습니다.
이 그림에 따르면, 개발 서버가 실행중인 웹 서버 소프트웨어는 Intellij Idea 15.0.4이며, 마지막으로 Apples.html 문서가 수정 된 것은 6 월 27 일 (그러나 스크린 샷은 7 월 5 일)입니다.