diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:43:23 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:43:23 -0500 |
commit | 218934fa2ed1c702a6d3923d2aa2cc6b43c48684 (patch) | |
tree | a9ef8ac1e1b8fe4207b6d64d3841bfb8990b6fd0 /files/zh-tw/web/api/xmlhttprequest | |
parent | 074785cea106179cb3305637055ab0a009ca74f2 (diff) | |
download | translated-content-218934fa2ed1c702a6d3923d2aa2cc6b43c48684.tar.gz translated-content-218934fa2ed1c702a6d3923d2aa2cc6b43c48684.tar.bz2 translated-content-218934fa2ed1c702a6d3923d2aa2cc6b43c48684.zip |
initial commit
Diffstat (limited to 'files/zh-tw/web/api/xmlhttprequest')
9 files changed, 1743 insertions, 0 deletions
diff --git a/files/zh-tw/web/api/xmlhttprequest/index.html b/files/zh-tw/web/api/xmlhttprequest/index.html new file mode 100644 index 0000000000..3258579e62 --- /dev/null +++ b/files/zh-tw/web/api/xmlhttprequest/index.html @@ -0,0 +1,177 @@ +--- +title: XMLHttpRequest +slug: Web/API/XMLHttpRequest +tags: + - AJAX + - Fixit + - HTTP + - MakeBrowserAgnostic + - NeedsCleanup + - NeedsMobileBrowserCompatibility + - NeedsTranslation + - TopicStub + - XMLHttpRequest +translation_of: Web/API/XMLHttpRequest +--- +<div>{{DefaultAPISidebar("XMLHttpRequest")}}</div> + +<p><span class="seoSummary">藉由 <code>XMLHttpRequest</code>(XHR)物件的方式來存取伺服器端的資料,可以讓你直接經由指定的 URL 擷取資料卻不用刷新整個網頁。這樣一來當想要更新網頁中的部分資料時,不再需要藉由刷新整個頁面的方法而中斷使用者的操作。在</span>{{Glossary("AJAX")}}應用中 <code>XMLHttpRequest</code> 被大量的使用。</p> + +<p>{{InheritanceDiagram(650, 150)}}</p> + +<p>雖然 <span class="seoSummary"><code>XMLHttpRequest</code></span> 這個物件的命名包含了 XML 與 HTTP 等字眼,但實際上 <code>XMLHttpRequest</code> 可用來接收任何類型的資料,不限於 XML 類型而已。</p> + +<p>如果在資料交換的時候,需要接收從伺服器端傳來的事件或訊息:可以考慮透過{{domxref("EventSource")}}介面使用<a href="/zh-TW/docs/Web/API/Server-sent_events">server-sent 事件</a>。對於和伺服器全雙工的資訊交換,<a href="/en-US/docs/Web/API/WebSockets_API">WebSockets</a> 可能是較佳的選擇。</p> + +<h2 id="建構式">建構式</h2> + +<dl> + <dt>{{domxref("XMLHttpRequest.XMLHttpRequest", "XMLHttpRequest()")}}</dt> + <dd>建構式用來初始化一個 <code>XMLHttpRequest</code> 物件。必須在其他任何所屬方法被呼叫之前被呼叫。</dd> +</dl> + +<h2 id="屬性">屬性</h2> + +<p><em>此介面也繼承了 {{domxref("XMLHttpRequestEventTarget")}} 及 {{domxref("EventTarget")}} 的屬性。</em></p> + +<dl> + <dt id="xmlhttprequest-onreadystatechange">{{domxref("XMLHttpRequest.onreadystatechange")}}</dt> + <dd>一個 {{domxref("EventHandler")}}(事件處理器)函式,會於 <code>readyState</code> 屬性之狀態改變時被呼叫。</dd> + <dt id="xmlhttprequest-readystate">{{domxref("XMLHttpRequest.readyState")}} {{readonlyinline}}</dt> + <dd>回傳一個無符號短整數(<code>unsigned short</code>)代表請求之狀態。</dd> + <dt>{{domxref("XMLHttpRequest.response")}} {{readonlyinline}}</dt> + <dd>回傳的內容可能是 {{domxref("ArrayBuffer")}}、{{domxref("Blob")}}、{{domxref("Document")}}、JavaScript 物件或 {{domxref("DOMString")}}。完全根據 {{domxref("XMLHttpRequest.responseType")}} 的值決定回傳的內容為何種型態,資料為回應實體中的內容(response entity body)。</dd> + <dt id="xmlhttprequest-responsetext">{{domxref("XMLHttpRequest.responseText")}} {{readonlyinline}}</dt> + <dd>回傳一個 {{domxref("DOMString")}},其內容為請求之回應的文字內容。如請求失敗或尚未發送,則為 <code>null</code>。</dd> + <dt id="xmlhttprequest-responsetype">{{domxref("XMLHttpRequest.responseType")}}</dt> + <dd>為一可列舉(enumerated)值,定義回應內容的資料類型(response type)。</dd> + <dt id="xmlhttprequest-responsexml">{{domxref("XMLHttpRequest.responseURL")}} {{readonlyinline}}</dt> + <dd>回傳一個回應(response)的序列化 URL,如 URL 為 null 則回傳空字串。</dd> + <dt id="xmlhttprequest-responsexml">{{domxref("XMLHttpRequest.responseXML")}} {{readonlyinline}}</dt> + <dd>回傳一個 {{domxref("Document")}},其內容為請求之回應內容所解析成的文件物件。如請求失敗或尚未發送,又或是無法解析成 XML、HTML,則為 <code>null</code>。Not available in workers.</dd> + <dt id="xmlhttprequest-status">{{domxref("XMLHttpRequest.status")}} {{readonlyinline}}</dt> + <dd>回傳一個無符號短整數(<code>unsigned short</code>)表示已發送請求之回應的狀態。</dd> + <dt id="xmlhttprequest-statustext">{{domxref("XMLHttpRequest.statusText")}} {{readonlyinline}}</dt> + <dd>回傳一個 {{domxref("DOMString")}} 表示 HTTP 伺服器回應之字串。和 {{domxref("XMLHTTPRequest.status")}} 不同的是,<code>XMLHttpRequest.statusText</code> 包含了回應的整個文字訊息(如 "<code>200 OK</code>")。</dd> +</dl> + +<div class="note"> +<p><strong>Note:</strong> The HTTP/2 specification (<a href="https://http2.github.io/http2-spec/#rfc.section.8.1.2.4">8.1.2.4</a> <a href="https://http2.github.io/http2-spec/#HttpResponse">Response Pseudo-Header Fields</a>), HTTP/2 does not define a way to carry the version or reason phrase that is included in an HTTP/1.1 status line.</p> +</div> + +<dl> + <dt id="xmlhttprequest-timeout">{{domxref("XMLHttpRequest.timeout")}}</dt> + <dd>為一無符號長整數(<code>unsigned long</code>),代表一個請求在逾時而被自動中止前的可等待時間(毫秒)。</dd> + <dt id="xmlhttprequesteventtarget-ontimeout">{{domxref("XMLHttpRequestEventTarget.ontimeout")}}</dt> + <dd>為一 {{domxref("EventHandler")}} 物件,會於請求逾時時被呼叫。{{gecko_minversion_inline("12.0")}}</dd> + <dt id="xmlhttprequest-upload">{{domxref("XMLHttpRequest.upload")}} {{readonlyinline}}</dt> + <dd>為一 {{domxref("XMLHttpRequestUpload")}} 物件,代表上傳的進度。</dd> + <dt id="xmlhttprequest-withcredentials">{{domxref("XMLHttpRequest.withCredentials")}}</dt> + <dd>{{domxref("Boolean","布林值")}}。表示是否允許在跨站存取(cross-site <code>Access-Control</code>)之請求當中,發送如 cookies 或 authorization headers 等憑證資訊(credentials)。</dd> +</dl> + +<h3 id="非標準屬性">非標準屬性</h3> + +<dl> + <dt>{{domxref("XMLHttpRequest.channel")}}{{ReadOnlyInline}}</dt> + <dd>是一個 {{Interface("nsIChannel")}}。當執行要求時,物件使用的頻道(Channel)。</dd> + <dt>{{domxref("XMLHttpRequest.mozAnon")}}{{ReadOnlyInline}}</dt> + <dd>為一個布林值。如果為真,請求就會以沒有cookie及authentication headers的方式送出。</dd> + <dt>{{domxref("XMLHttpRequest.mozSystem")}}{{ReadOnlyInline}}</dt> + <dd>這是一個布林值。If true, the same origin policy will not be enforced on the request.</dd> + <dt>{{domxref("XMLHttpRequest.mozBackgroundRequest")}}</dt> + <dd>這是一個布林值。指出該物件是否為一個背景型態的服務要求。</dd> + <dt>{{domxref("XMLHttpRequest.mozResponseArrayBuffer")}}{{gecko_minversion_inline("2.0")}} {{obsolete_inline("6")}} {{ReadOnlyInline}}</dt> + <dd>Is an <a href="/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer"><code>ArrayBuffer</code></a>. The response to the request, as a JavaScript typed array.</dd> + <dt>{{domxref("XMLHttpRequest.multipart")}}{{obsolete_inline("22")}}</dt> + <dd><strong>This Gecko-only feature, a boolean, was removed in Firefox/Gecko 22.</strong> Please use <a href="/zh-TW/docs/Web/API/Server-sent_events">Server-Sent Events</a>, <a href="/zh-TW/docs/Web/API/WebSockets_API">Web Sockets</a>, or <code>responseText</code> from progress events instead.</dd> +</dl> + +<h3 id="事件處理器">事件處理器</h3> + +<p>所有瀏覽器都支援 <code>XMLHttpRequest</code> 物件實體的 <code>onreadystatechange</code> 屬性。</p> + +<p>之後,各個瀏覽器實作了多種額外的事件處理器(如 <code>onload</code>、<code>onerror</code>、<code>onprogress</code> 等)。請參考<a href="https://developer.mozilla.org/zh-TW/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest">使用 XMLHttpRequest</a>。</p> + +<p>除了以 <code>on*</code> 屬性來設定事件處理函式,更多現代覽瀏器(包括 Firefox)也支援使用標準的 <code><a href="/zh-TW/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code> API 註冊監聽 <code>XMLHttpRequest</code> 的事件。</p> + +<dl> +</dl> + +<h2 id="方法">方法</h2> + +<dl> + <dt>{{domxref("XMLHttpRequest.abort()")}}</dt> + <dd>中止已發出的請求。</dd> + <dt>{{domxref("XMLHttpRequest.getAllResponseHeaders()")}}</dt> + <dd>回傳所有的回應標頭(response headers),為一以斷行字元(<a href="/zh-TW/docs/Glossary/CRLF">CRLF</a>)分行的字串,如未接收到回應則為 <code>null</code>。</dd> + <dt>{{domxref("XMLHttpRequest.getResponseHeader()")}}</dt> + <dd>回傳指定標頭文字之字串,假如回應尚未被接收或是標頭不存在於回應中則為 <code>null</code>。</dd> + <dt>{{domxref("XMLHttpRequest.open()")}}</dt> + <dd>初始化一個請求。此方法用於 JavaScript 中;若要在 native code 中初始化請求,請以 <a class="internal" href="/zh-TW/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIXMLHttpRequest#openRequest()"><code>openRequest()</code></a> 作為替代。</dd> + <dt>{{domxref("XMLHttpRequest.overrideMimeType()")}}</dt> + <dd>覆寫伺服器回傳的 MIME type。</dd> + <dt>{{domxref("XMLHttpRequest.send()")}}<span style="display: none;"> </span></dt> + <dd>發送請求。如果為非同步請求(預設值),此方法將在發出請求後便立即回傳(return)。</dd> + <dt>{{domxref("XMLHttpRequest.setRequestHeader()")}}</dt> + <dd>設定 HTTP 請求標頭(request header)值。<code>setRequestHeader()</code> 可被呼叫的時間點必須於 <a href="#open"><code>open()</code></a> 之後、在 <code>send()</code> 之前。</dd> +</dl> + +<h3 id="非標準方法">非標準方法</h3> + +<dl> + <dt>{{domxref("XMLHttpRequest.init()")}}</dt> + <dd>使用 C++ 程式時,用來初始化這個物件。</dd> +</dl> + +<div class="warning"><strong>注意:</strong> 請勿在 JavaScript 中呼叫這個方法。</div> + +<dl> + <dt>{{domxref("XMLHttpRequest.openRequest()")}}</dt> + <dd>初始化請求。這方法是用於原生程式,若想在 JavaScript 中初始化一個請求,請使用 <a class="internal" href="/zh-TW/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIXMLHttpRequest#open()"><code>open()</code></a> 這個方法來代替。請參照 <code>open()</code> 的相關文件。</dd> + <dt>{{domxref("XMLHttpRequest.sendAsBinary()")}}{{deprecated_inline()}}</dt> + <dd>另一種 <code>send()</code> 方法,用來送出二進位資料。</dd> +</dl> + +<h2 id="規範">規範</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">規範</th> + <th scope="col">狀態</th> + <th scope="col">註解</th> + </tr> + <tr> + <td>{{SpecName('XMLHttpRequest')}}</td> + <td>{{Spec2('XMLHttpRequest')}}</td> + <td>Live standard, latest version</td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + + + +<div>{{Compat("api.XMLHttpRequest")}}</div> + +<h2 id="參見">參見</h2> + +<ul> + <li>MDN 上涵蓋 XMLHttpRequest 的相關教學: + <ul> + <li><a href="/zh-TW/docs/AJAX/Getting_Started">Ajax — Getting Started</a></li> + <li><a href="/zh-TW/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest">使用 XMLHttpRequest</a></li> + <li><a href="/zh-TW/docs/Web/API/XMLHttpRequest/HTML_in_XMLHttpRequest">HTML in XMLHttpRequest</a></li> + <li><a href="/zh-TW/docs/Web/API/FormData"><code>FormData</code></a></li> + </ul> + </li> + <li><a class="external" href="http://www.html5rocks.com/en/tutorials/file/xhr2/">HTML5 Rocks — New Tricks in XMLHttpRequest2</a></li> + <li><code>Chrome scope availability</code> — how to access XMLHttpRequest from JSM modules etc., which do not have access to DOM + <ul> + <li><a href="/zh-TW/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.importGlobalProperties">Components.utils.importGlobalProperties</a></li> + <li><a href="/zh-TW/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIXMLHttpRequest">nsIXMLHttpRequest</a></li> + </ul> + </li> +</ul> diff --git a/files/zh-tw/web/api/xmlhttprequest/onreadystatechange/index.html b/files/zh-tw/web/api/xmlhttprequest/onreadystatechange/index.html new file mode 100644 index 0000000000..817daf0efa --- /dev/null +++ b/files/zh-tw/web/api/xmlhttprequest/onreadystatechange/index.html @@ -0,0 +1,113 @@ +--- +title: XMLHttpRequest.onreadystatechange +slug: Web/API/XMLHttpRequest/onreadystatechange +translation_of: Web/API/XMLHttpRequest/onreadystatechange +--- +<div>{{APIRef}}</div> + +<p>An <a href="/docs/Web/API/EventHandler" title="A possible way to get notified of Events of a particular type (such as click) for a given object is to specify an event handler using:"><code>EventHandler</code></a> that is called whenever the <code>readyState</code> attribute changes. The callback is called from the user interface thread. The <strong><code>XMLHttpRequest.onreadystatechange</code></strong> property contains the event handler to be called when the {{event("readystatechange")}} event is fired, that is every time the {{domxref("XMLHttpRequest.readyState", "readyState")}} property of the {{domxref("XMLHttpRequest")}} changes.</p> + +<div class="warning"> +<p><strong>Warning:</strong> This should not be used with synchronous requests and must not be used from native code.</p> +</div> + +<p>The <code>readystatechange</code> event will not be fired when an <code>XMLHttpRequest</code> request is cancelled with the <a href="/docs/Web/API/XMLHttpRequest/abort">abort()</a> method.</p> + +<div class="note"> +<p>UPDATE: it's firing in the latest version of browsers (Firefox 51.0.1, Opera 43.0.2442.991, Safari 10.0.3 (12602.4.8), Chrome 54.0.2840.71, Edge, IE11). Example <a href="https://jsfiddle.net/merksam/ve5oc0gn/">here</a> - just reaload page few times.</p> +</div> + +<h2 id="Syntax" name="Syntax">語法</h2> + +<pre class="syntaxbox"><em>XMLHttpRequest</em>.onreadystatechange = <em>callback</em>;</pre> + +<h3 id="值">值</h3> + +<ul> + <li><code><em>callback</em></code> is the function to be executed when the <code>readyState</code> changes.</li> +</ul> + +<h2 id="Example" name="Example">範例</h2> + +<pre class="brush: js">var xhr = new XMLHttpRequest(), + method = "GET", + url = "https://developer.mozilla.org/"; + +xhr.open(<em>method</em>, <em>url</em>, true); +xhr.onreadystatechange = function () { + if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) { + console.log(xhr.responseText); + } + }; +xhr.send();</pre> + +<h2 id="規範">規範</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('XMLHttpRequest', '#handler-xhr-onreadystatechange')}}</td> + <td>{{Spec2('XMLHttpRequest')}}</td> + <td>WHATWG living standard</td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<p>{{CompatibilityTable}}</p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatChrome(1)}}</td> + <td>{{CompatGeckoDesktop(1.0)}}</td> + <td>{{CompatIe(7)}}<sup>[1]</sup></td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatSafari(1.2)}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>1.0</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<p>[1] Internet Explorer version 5 and 6 supported ajax calls using <code>ActiveXObject()</code>.</p> diff --git a/files/zh-tw/web/api/xmlhttprequest/readystate/index.html b/files/zh-tw/web/api/xmlhttprequest/readystate/index.html new file mode 100644 index 0000000000..3f7e909fe0 --- /dev/null +++ b/files/zh-tw/web/api/xmlhttprequest/readystate/index.html @@ -0,0 +1,148 @@ +--- +title: XMLHttpRequest.readyState +slug: Web/API/XMLHttpRequest/readyState +translation_of: Web/API/XMLHttpRequest/readyState +--- +<p>{{APIRef('XMLHttpRequest')}}</p> + +<p><strong>XMLHttpRequest.readyState</strong> 屬性會回傳一個 XMLHttpRequest 客戶端物件目前的狀態。一個 <abbr title="XMLHttpRequest">XHR</abbr> 客戶端可以為下列其中一種狀態:</p> + +<table class="standard-table"> + <tbody> + <tr> + <td class="header">值</td> + <td class="header">狀態</td> + <td class="header">說明</td> + </tr> + <tr> + <td><code>0</code></td> + <td><code>UNSENT</code></td> + <td>客戶端已被建立,但 <code>open()</code> 方法尚未被呼叫。</td> + </tr> + <tr> + <td><code>1</code></td> + <td><code>OPENED</code></td> + <td><code>open()</code> 方法已被呼叫。</td> + </tr> + <tr> + <td><code>2</code></td> + <td><code>HEADERS_RECEIVED</code></td> + <td><code>send()</code> 方法已被呼叫,而且可取得 header 與狀態。</td> + </tr> + <tr> + <td><code>3</code></td> + <td><code>LOADING</code></td> + <td>回應資料下載中,此時 <code>responseText</code> 會擁有部分資料。</td> + </tr> + <tr> + <td><code>4</code></td> + <td><code>DONE</code></td> + <td>完成下載操作。</td> + </tr> + </tbody> +</table> + +<dl> + <dt>UNSENT</dt> + <dd>XMLHttpRequest 客戶端物件已被建立,但 open() 方法尚未被呼叫。</dd> + <dt>OPENED</dt> + <dd>open() 方法已被呼叫。於此狀態時,可以使用 <a href="/zh-TW/docs/Web/API/XMLHttpRequest/setRequestHeader">setRequestHeader()</a> 方法設定請求標頭(request headers),並可呼叫 <a href="/zh-TW/docs/Web/API/XMLHttpRequest/send">send()</a> 方法來發送請求。</dd> + <dt>HEADERS_RECEIVED</dt> + <dd>send() 方法已被呼叫,並且已接收到回應標頭(response header)。</dd> + <dt>LOADING</dt> + <dd>正在接收回應內容(response's body)。如 <code><a href="/zh-TW/docs/Web/API/XMLHttpRequest/responseType">responseType</a></code> 屬性為 "text" 或空字串,則 <code><a href="/zh-TW/docs/Web/API/XMLHttpRequest/responseText">responseText</a></code> 屬性將會在載入的過程中擁有已載入部分之回應(response)內容中的文字。</dd> + <dt>DONE</dt> + <dd>請求操作已完成。這意味著資料傳輸可能已成功完成或是已失敗。</dd> +</dl> + +<div class="note"> +<p>這些狀態名稱在 Internet Explorer 中略有不同。其中 <code>UNSENT</code>, <code>OPENED</code>,<code> HEADERS_RECEIVED</code>,<code> LOADING</code> 和 <code>DONE 變成了 READYSTATE_UNINITIALIZED</code> (0), <code>READYSTATE_LOADING</code> (1), <code>READYSTATE_LOADED</code> (2), <code>READYSTATE_INTERACTIVE</code> (3) 和<code>READYSTATE_COMPLETE</code> (4)。</p> +</div> + +<h2 id="範例">範例</h2> + +<pre class="brush: js">var xhr = new XMLHttpRequest(); +console.log('UNSENT', xhr.readyState); // readyState will be 0 + +xhr.open('GET', '/api', true); +console.log('OPENED', xhr.readyState); // readyState will be 1 + +xhr.onprogress = function () { + console.log('LOADING', xhr.readyState); // readyState will be 3 +}; + +xhr.onload = function () { + console.log('DONE', xhr.readyState); // readyState will be 4 +}; + +xhr.send(null); +</pre> + +<h2 id="規範">規範</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">規範</th> + <th scope="col">狀態</th> + <th scope="col">註解</th> + </tr> + <tr> + <td>{{SpecName('XMLHttpRequest', '#states')}}</td> + <td>{{Spec2('XMLHttpRequest')}}</td> + <td>WHATWG living standard</td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>功能</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari (WebKit)</th> + </tr> + <tr> + <td>基本支援</td> + <td>{{CompatChrome(1)}}</td> + <td>{{CompatGeckoDesktop("1.0")}}<sup>[1]</sup></td> + <td>{{CompatIe(7)}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatSafari("1.2")}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>功能</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>基本支援</td> + <td>{{CompatUnknown}}</td> + <td>1.0</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> diff --git a/files/zh-tw/web/api/xmlhttprequest/setrequestheader/index.html b/files/zh-tw/web/api/xmlhttprequest/setrequestheader/index.html new file mode 100644 index 0000000000..a8219e7240 --- /dev/null +++ b/files/zh-tw/web/api/xmlhttprequest/setrequestheader/index.html @@ -0,0 +1,66 @@ +--- +title: XMLHttpRequest.setRequestHeader() +slug: Web/API/XMLHttpRequest/setRequestHeader +translation_of: Web/API/XMLHttpRequest/setRequestHeader +--- +<div>{{APIRef('XMLHttpRequest')}}</div> + +<p>{{domxref("XMLHttpRequest")}} 物件中的 <code><strong>setRequestHeader()</strong></code> 方法用來設定 HTTP 的表頭請求。當使用 <code>setRequestHeader()</code> 的時候,必須在 {{domxref("XMLHttpRequest.open", "open()")}} 之後呼叫,同時也必須在 {{domxref("XMLHttpRequest.send", "send()")}} 之前呼叫。如果這個方法被呼叫了許多次,且設定的表頭是一樣的,那所有設定的值會被合併成一個單一的表頭請求。</p> + +<p>在第一次呼叫 <code>setRequestHeader()</code> 之後的每一次的呼叫,都會把給定的文字附加在已存在的表頭內容之後。</p> + +<p>If no {{HTTPHeader("Accept")}} header has been set using this, an <code>Accept</code> header with the type <code>"*/*"</code> is sent with the request when {{domxref("XMLHttpRequest.send", "send()")}} is called.</p> + +<p>基於安全的理由,有些表頭只有使用者代理器可以使用。這些表頭包含了: {{Glossary("Forbidden_header_name", "forbidden header names", 1)}} 和 {{Glossary("Forbidden_response_header_name", "forbidden response header names", 1)}}.</p> + +<div class="note"> +<p><strong>Note:</strong> For your custom fields, you may encounter a "<strong>not allowed by Access-Control-Allow-Headers in preflight response</strong>" exception when you send requests across domains. In this situation, you need to set up the {{HTTPHeader("Access-Control-Allow-Headers")}} in your response header at server side.</p> +</div> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox"><em>XMLHttpRequest</em>.setRequestHeader(<var>header</var>, <var>value</var>) +</pre> + +<h3 id="參數">參數</h3> + +<dl> + <dt><code>header</code></dt> + <dd>想要設定所屬值的表頭名稱。</dd> + <dt><code>value</code></dt> + <dd>用來設定表頭本身的值。</dd> +</dl> + +<h3 id="回傳值">回傳值</h3> + +<p><font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">未定義</span></font>。</p> + +<h2 id="規範">規範</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('XMLHttpRequest', '#the-setrequestheader()-method', 'setRequestHeader()')}}</td> + <td>{{Spec2('XMLHttpRequest')}}</td> + <td>WHATWG living standard</td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + + + +<p>{{Compat("api.XMLHttpRequest.setRequestHeader")}}</p> + +<h2 id="參見">參見</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest">Using XMLHttpRequest</a></li> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest/HTML_in_XMLHttpRequest">HTML in XMLHttpRequest</a></li> +</ul> diff --git a/files/zh-tw/web/api/xmlhttprequest/status/index.html b/files/zh-tw/web/api/xmlhttprequest/status/index.html new file mode 100644 index 0000000000..c54ece9939 --- /dev/null +++ b/files/zh-tw/web/api/xmlhttprequest/status/index.html @@ -0,0 +1,115 @@ +--- +title: XMLHttpRequest.status +slug: Web/API/XMLHttpRequest/status +translation_of: Web/API/XMLHttpRequest/status +--- +<div>{{APIRef('XMLHttpRequest')}}</div> + +<p><strong>XMLHttpRequest.status</strong> 屬性根據XMLHttpRequest的回應傳回數值化的狀況編碼。狀況編碼為一正短整數(<code>unsigned short)。</code>Before the request is complete, the value of <code>status</code> will be <code>0</code>. It is worth noting that browsers report a status of 0 in case of XMLHttpRequest errors too.</p> + +<p>The status codes returned are the standard <a href="/en-US/docs/Web/HTTP/Response_codes">HTTP status codes</a>. For example, <code>status</code> <code>200</code> denotes a successful request. If the server response doesn't explicitly specify a status code, <code>XMLHttpRequest.status</code> will assume the default value of <code>200</code>.</p> + +<h2 id="Example">Example</h2> + +<pre class="brush: js">var xhr = new XMLHttpRequest(); +console.log('UNSENT', xhr.status); + +xhr.open('GET', '/server', true); +console.log('OPENED', xhr.status); + +xhr.onprogress = function () { + console.log('LOADING', xhr.status); +}; + +xhr.onload = function () { + console.log('DONE', xhr.status); +}; + +xhr.send(null); + +/** + * Outputs the following: + * + * UNSENT 0 + * OPENED 0 + * LOADING 200 + * DONE 200 + */ +</pre> + +<h2 id="Specifications">Specifications</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('XMLHttpRequest', '#the-status-attribute')}}</td> + <td>{{Spec2('XMLHttpRequest')}}</td> + <td>WHATWG living standard</td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility">Browser compatibility</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari (WebKit)</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatChrome(1)}}</td> + <td>{{CompatGeckoDesktop("1.0")}}<sup>[1]</sup></td> + <td>{{CompatIe(7)}}<sup>[1]</sup></td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatSafari("1.2")}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>1.0</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<p>[1] Internet Explorer versions 5 and 6 lacked the XMLHttpRequest object, but provided a way to make AJAX requests using <code>ActiveXObject</code>.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li>List of <a href="/en-US/docs/Web/HTTP/Response_codes">HTTP response codes</a></li> +</ul> diff --git a/files/zh-tw/web/api/xmlhttprequest/synchronous_and_asynchronous_requests/index.html b/files/zh-tw/web/api/xmlhttprequest/synchronous_and_asynchronous_requests/index.html new file mode 100644 index 0000000000..e8a148b5a9 --- /dev/null +++ b/files/zh-tw/web/api/xmlhttprequest/synchronous_and_asynchronous_requests/index.html @@ -0,0 +1,260 @@ +--- +title: Synchronous and asynchronous requests +slug: Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests +translation_of: Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests +--- +<p><code>XMLHttpRequest 支持同步和非同步請求,一般來說,建議使用非同步請求。</code></p> + +<p>In short, synchronous requests block the execution of code which creates "freezing" on the screen and an unresponsive user experience. </p> + +<h2 id="非同步請求">非同步請求</h2> + +<p>If you use <code>XMLHttpRequest</code> from an extension, you should use it asynchronously. In this case, you receive a callback when the data has been received, which lets the browser continue to work as normal while your request is being handled.</p> + +<h3 id="範例_send_a_file_to_the_console_log">範例: send a file to the console log</h3> + +<p>這是使用非同步<span style="font-family: consolas,monaco,andale mono,monospace;">XMLHttpRequest的基本方式</span></p> + +<pre class="brush: js">var xhr = new XMLHttpRequest(); +xhr.open("GET", "/bar/foo.txt", true); +xhr.onload = function (e) { + if (xhr.readyState === 4) { + if (xhr.status === 200) { + console.log(xhr.responseText); + } else { + console.error(xhr.statusText); + } + } +}; +xhr.onerror = function (e) { + console.error(xhr.statusText); +}; +xhr.send(null); </pre> + +<p>Line 2第3個參數為布林值,true表示非同步請求。</p> + +<p>Line 3 creates an event handler function object and assigns it to the request's <code>onload</code> attribute. This handler looks at the request's <code>readyState</code> to see if the transaction is complete in line 4, and if it is, and the HTTP status is 200, dumps the received content. If an error occurred, an error message is displayed.</p> + +<p>Line 15 actually initiates the request. The callback routine is called whenever the state of the request changes.</p> + +<h3 id="Example_creating_a_standard_function_to_read_external_files">Example: creating a standard function to read external files</h3> + +<p>In some cases you must read many external files. This is a standard function which uses the <code>XMLHttpRequest</code> object asynchronously in order to switch the content of the read file to a specified listener.</p> + +<pre class="brush: js">function xhrSuccess () { this.callback.apply(this, this.arguments); } + +function xhrError () { console.error(this.statusText); } + +function loadFile (sURL, fCallback /*, argumentToPass1, argumentToPass2, etc. */) { + var oReq = new XMLHttpRequest(); + oReq.callback = fCallback; + oReq.arguments = Array.prototype.slice.call(arguments, 2); + oReq.onload = xhrSuccess; + oReq.onerror = xhrError; + oReq.open("get", sURL, true); + oReq.send(null); +} +</pre> + +<p>Usage:</p> + +<pre class="brush: js">function showMessage (sMsg) { + alert(sMsg + this.responseText); +} + +loadFile("message.txt", showMessage, "New message!\n\n"); +</pre> + +<p>Line 1 declares a function which will pass all arguments after the third to the <font face="Courier New, Andale Mono, monospace"><span style="line-height: normal;">callback </span></font>function when the file has been loaded.</p> + +<p>Line 4 creates an event handler function object and assigns it to the request's <code>onload</code> attribute. This handler looks at the request's <code>readyState</code> to see if the transaction is complete in line 5, and if it is, and the HTTP status is 200, calls the callback function. If an error occurred, an error message is displayed.</p> + +<p>Line 13 specifies <code>true</code> for its third parameter to indicate that the request should be handled asynchronously.</p> + +<p>Line 14 actually initiates the request.</p> + +<h3 id="Example_using_a_timeout">Example: using a timeout</h3> + +<p>You can use a timeout to prevent hanging your code forever while waiting for a read to occur. This is done by setting the value of the <code>timeout</code> property on the <code>XMLHttpRequest</code> object, as shown in the code below:</p> + +<pre class="brush: js"> var args = arguments.slice(2); + var xhr = new XMLHttpRequest(); + xhr.ontimeout = function () { + console.error("The request for " + url + " timed out."); + }; + xhr.onload = function() { + if (xhr.readyState === 4) { + if (xhr.status === 200) { + callback.apply(xhr, args); + } else { + console.error(xhr.statusText); + } + } + }; + xhr.open("GET", url, true); + xhr.timeout = timeout; + xhr.send(null); +} +</pre> + +<p>Notice the addition of code to handle the "timeout" event by setting the <code>ontimeout</code> handler.</p> + +<p>Usage:</p> + +<pre class="brush: js">function showMessage (sMsg) { + alert(sMsg + this.responseText); +} + +loadFile("message.txt", 2000, showMessage, "New message!\n"); +</pre> + +<p>Here, we're specifying a timeout of 2000 ms.</p> + +<div class="note"> +<p><strong>Note:</strong> Support for <code>timeout</code> was added in {{Gecko("12.0")}}.</p> +</div> + +<h2 id="Synchronous_request">Synchronous request</h2> + +<div class="note"><strong>Note:</strong> Starting with Gecko 30.0 {{ geckoRelease("30.0") }}, synchronous requests on the main thread have been deprecated due to the negative effects to the user experience.</div> + +<p>In rare cases, the use of a synchronous method is preferable to an asynchronous one.</p> + +<h3 id="Example_HTTP_synchronous_request">Example: HTTP synchronous request</h3> + +<p>This example demonstrates how to make a simple synchronous request.</p> + +<pre class="brush: js">var request = new XMLHttpRequest(); +request.open('GET', '/bar/foo.txt', false); // `false` makes the request synchronous +request.send(null); + +if (request.status === 200) { + console.log(request.responseText); +} +</pre> + +<p>Line 3 sends the request. The <code>null</code> parameter indicates that no body content is needed for the <code>GET</code> request.</p> + +<p>Line 5 checks the status code after the transaction is completed. If the result is 200 -- HTTP's "OK" result -- the document's text content is output to the console.</p> + +<h3 id="Example_Synchronous_HTTP_request_from_a_Worker">Example: Synchronous HTTP request from a <code>Worker</code></h3> + +<p>One of the few cases in which a synchronous request does not usually block execution is the use of <code>XMLHttpRequest</code> within a <code><a href="/en/DOM/Worker" title="/en/DOM/Worker">Worker</a></code>.</p> + +<p><code><strong>example.html</strong></code> (the main page):</p> + +<pre class="brush: html"><!doctype html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<title>MDN Example</title> +<script type="text/javascript"> + var worker = new Worker("myTask.js"); + worker.onmessage = function(event) { + alert("Worker said: " + event.data); + }; + + worker.postMessage("Hello"); +</script> +</head> +<body></body> +</html> +</pre> + +<p><code><strong>myFile.txt</strong></code> (the target of the synchronous <code><a href="/en/DOM/XMLHttpRequest" title="/en/XMLHttpRequest">XMLHttpRequest</a></code> invocation):</p> + +<pre>Hello World!! +</pre> + +<p><code><strong>myTask.js</strong></code> (the <code><a href="/en/DOM/Worker" title="/en/DOM/Worker">Worker</a></code>):</p> + +<pre class="brush: js">self.onmessage = function (event) { + if (event.data === "Hello") { + var xhr = new XMLHttpRequest(); + xhr.open("GET", "myFile.txt", false); // synchronous request + xhr.send(null); + self.postMessage(xhr.responseText); + } +}; +</pre> + +<div class="note"><strong>Note:</strong> The effect, because of the use of the <code>Worker</code>, is however asynchronous.</div> + +<p>It could be useful in order to interact in background with the server or to preload some content. See <a class="internal" href="/En/DOM/Using_web_workers" title="en/Using DOM workers">Using web workers</a> for examples and details.</p> + +<h3 id="Irreplaceability_of_the_synchronous_use">Irreplaceability of the synchronous use</h3> + +<p>There are some few cases in which the synchronous usage of XMLHttpRequest is not replaceable. This happens for example during the <a class="internal" href="/en/DOM/window.onunload" title="en/DOM/window.onunload"><code>window.onunload</code></a> and <a class="internal" href="/en/DOM/window.onbeforeunload" title="en/DOM/window.onbeforeunload"><code>window.onbeforeunload</code></a> events (<a class="internal" href="#XMLHttpRequests_being_stopped" title="en/XMLHttpRequest/Using_XMLHttpRequest#XMLHttpRequests_being_stopped">see also below</a>).</p> + +<p>Sending the usual XMLHttpRequest when the page unloaded poses a problem with the asynchronous response from the server: by the time the response comes back, the page has unloaded and the callback function won’t exist anymore. This generates a JavaScript “function is not defined” error.</p> + +<p style="text-align: center;"><img alt="" class="internal" src="/@api/deki/files/6227/=AsyncUnload.jpg" style="height: 359px; width: 467px;"></p> + +<p>A possible solution is to make sure that any AJAX requests that you make on unload are make synchronously instead of asynchronously. This will ensure that the page doesn’t finish unloading before the server response comes back.</p> + +<h4 id="Example_1_Automatic_logout_before_exit">Example #1: Automatic logout before exit</h4> + +<pre class="brush: js">window.onbeforeunload = function () { + var xhr = new XMLHttpRequest(); + xhr.open("GET", "logout.php?nick=" + escape(myName), false); // synchronous request + xhr.send(null); + if (xhr.responseText.trim() !== "logout done"); { // "logout done" is the expected response text + return "Logout has failed. Do you want to complete it manually?"; + } +}; +</pre> + +<h4 id="Example_2_Noting_if_a_user_abandon_the_site_without_clicking_any_link_and_registering_the_boring_page">Example #2: Noting if a user abandon the site without clicking any link and registering the boring page</h4> + +<pre class="brush: js"><!doctype html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<title>MDN Example</title> +<script type="text/javascript"> +(function () { + + function dontPanic () { + bForsake = false; + return true; + } + + onload = function () { + for ( + var aLinks = document.links, nLen = aLinks.length, nIdx = 0; + nIdx < nLen; + aLinks[nIdx++].onclick = dontPanic + ); + }; + + onbeforeunload = function () { + if (bForsake) { + /* silent synchronous request */ + var oReq = new XMLHttpRequest(); + oReq.open("GET", "exit.php?leave=" + escape(location.href), false); + oReq.send(null); + } + }; + + var bForsake = true; + +})(); +</script> +</head> + +<body> + +<p><a href="https://developer.mozilla.org/">Example link</a></p> + +</body> +</html></pre> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest" title="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest"><code>XMLHttpRequest</code></a></li> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest" title="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest">Using XMLHttpRequest</a></li> + <li><a href="/en-US/docs/AJAX" title="/en-US/docs/AJAX">AJAX</a></li> +</ul> + +<p>{{ languages( {"zh-cn": "zh-cn/DOM/XMLHttpRequest/Synchronous_and_Asynchronous_Requests" } ) }}</p> diff --git a/files/zh-tw/web/api/xmlhttprequest/using_xmlhttprequest/index.html b/files/zh-tw/web/api/xmlhttprequest/using_xmlhttprequest/index.html new file mode 100644 index 0000000000..97b03c21d1 --- /dev/null +++ b/files/zh-tw/web/api/xmlhttprequest/using_xmlhttprequest/index.html @@ -0,0 +1,766 @@ +--- +title: 使用 XMLHttpRequest +slug: Web/API/XMLHttpRequest/Using_XMLHttpRequest +tags: + - AJAX + - AJAXfile + - Advanced + - DOM + - JXON + - MakeBrowserAgnostic + - NeedsCompatTable + - XML + - XMLHttpRequest +translation_of: Web/API/XMLHttpRequest/Using_XMLHttpRequest +--- +<p>要送出一個 HTTP 請求,需要建立一個 {{domxref("XMLHttpRequest")}} 物件、開啟一個 URL,並發起一個請求。在交易(transaction)完成後,<code>XMLHttpRequest</code> 物件將會包含如回應內容(response body)及 <a href="/docs/Web/HTTP/Status">HTTP 狀態</a>等等請求結果中的有用資訊。本頁概述了一些常見的、甚至略為難理解的 <code>XMLHttpRequest</code> 物件使用案例。</p> + +<pre class="brush: js">function reqListener () { + console.log(this.responseText); +} + +var oReq = new XMLHttpRequest(); +oReq.addEventListener("load", reqListener); +oReq.open("GET", "http://www.example.org/example.txt"); +oReq.send();</pre> + +<h2 id="請求類型">請求類型</h2> + +<p>透過 <code>XMLHttpRequest</code> 建立的請求,其取得資料的方式可以為非同步(asynchronously)或同步(synchronously)兩種之一。請求的種類是由 {{domxref("XMLHttpRequest.open()")}} 方法的選擇性參數 <code>async</code>(第三個參數)決定。若 <code>async</code> 參數為 <code>true</code> 或是未指定,<code>XMLHttpRequest</code> 會被設定為非同步,相反的若為 <code>false</code> 則會被設定為同步。這兩種請求類型的細節討論與示範可以在<a href="/docs/DOM/XMLHttpRequest/Synchronous_and_Asynchronous_Requests">同步與非同步請求</a>頁面中找到。一般來說,很少會使用到同步請求。</p> + +<div class="note"><strong>備註:</strong>自 Gecko 30.0 {{ geckoRelease("30.0") }} 開始,在主執行緒上的同步請求因其差勁的使用者體驗已被棄用。</div> + +<h2 id="處理回應">處理回應</h2> + +<p><code>XMLHttpRequest</code> 的活動標準規範(living standard specification)定義了數個 <code>XMLHttpRequest</code> 建構出之物件的<a href="https://xhr.spec.whatwg.org/">回應屬性</a>。這些回應屬性告訴客戶端關於 <code>XMLHttpRequest</code> 回應狀態的重要資訊。一些處理非文字類型回應的案例可能會需要一些在下面小節所說明的分析和操作。</p> + +<h3 id="分析及操作_responseXML_屬性">分析及操作 <code>responseXML</code> 屬性</h3> + +<p>透過 <code>XMLHttpRequest</code> 取得一個遠端的 XML 文件內容時,<code>responseXML</code> 屬性({{Glossary("property/JavaScript", "property")}})將會是一個由 XML 文件解析而來的 DOM 物件。這可能會造成分析和操作上的一些困難,以下有四種主要的 XML 文件分析方式:</p> + +<ol> + <li>利用 <a href="/docs/Web/XPath">XPath</a> 指向需要部份。</li> + <li>手動的<a href="/docs/Web/Guide/Parsing_and_serializing_XML">解析與序列化 XML</a> 成字串或物件。</li> + <li>利用 {{domxref("XMLSerializer")}} 來序列化 <strong>DOM 樹成字串或檔案</strong>。</li> + <li>如果事先知道 XML 文件內容,可利用 {{jsxref("RegExp")}}。如果換行符號會影響 <code>RegExp</code> 掃描結果,則需要移除換行符號。然而,這項方式應該是「最後不得已的手段(last resort)」,因為一旦 XML 文件內容稍有變動,此方式就可能會失敗。</li> +</ol> + +<h3 id="分析及操作含有_HTML_文件的_responseText_屬性">分析及操作含有 HTML 文件的 <code>responseText</code> 屬性</h3> + +<div class="note"><strong>備註:</strong>W3C 的<a href="https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html">XMLHttpRequest</a> 規範允許透過 <code>XMLHttpRequest.responseXML</code> 屬性({{Glossary("property/JavaScript", "property")}})來解析 HTML。相關細節請參考 <a href="/docs/Web/API/XMLHttpRequest/HTML_in_XMLHttpRequest">HTML in XMLHttpRequest</a> 一文。</div> + +<p>若透過 <code>XMLHttpRequest</code> 來取得一個遠端的 HTML 網頁內容,則 <code>responseText</code> 屬性({{Glossary("property/JavaScript", "property")}})會是「一串(soup)」包含所有 HTML 標籤的字串。這可能使得在分析和操作上造成困難,以下有三種主要分析此一大串 HTML 字串的方式:</p> + +<ol> + <li>利用 <code>XMLHttpRequest.responseXML</code> 屬性。</li> + <li>將內容透過 <code>fragment.body.innerHTML</code> 注入<a href="/docs/Web/API/DocumentFragment">文件片段(document fragment)</a>之 <code>body</code> 中,並遍歷(traverse)文件片段的 DOM。</li> + <li>如果事先知道 HTML 之 <code>responseText</code> 內容,可利用 {{jsxref("RegExp")}}。如果換行符號會影響 <code>RegExp</code> 掃描結果,則需要移除換行符號。然而,這項方式應該是「最後不得已的手段(last resort)」,因為一旦 HTML 程式碼稍有變動,此方式就可能會失敗。</li> +</ol> + +<h2 id="處理二進位資料">處理二進位資料</h2> + +<p>僅管 <code>XMLHttpRequest</code> 最常被用在傳送及接收文字資料,但它其實也可以傳送及接收二進位內容。有幾種經過良好測試的方法可以用來強制使用 <code>XMLHttpRequest</code> 發送二進位資料。透過使用 <code>XMLHttpRequest</code> 物件的 <code>.overrideMimeType()</code> 方法是一個可行的解決方案。</p> + +<pre class="brush:js">var oReq = new XMLHttpRequest(); +oReq.open("GET", url); +// retrieve data unprocessed as a binary string +oReq.overrideMimeType("text/plain; charset=x-user-defined"); +/* ... */ +</pre> + +<p>XMLHttpRequest Level 2 規範加入了新的 <a href="https://xhr.spec.whatwg.org/#the-responsetype-attribute"><code>responseType</code> 屬性</a>,讓收發二進位資料變得容易許多。</p> + +<pre class="brush:js">var oReq = new XMLHttpRequest(); + +oReq.onload = function(e) { + var arraybuffer = oReq.response; // not responseText + /* ... */ +} +oReq.open("GET", url); +oReq.responseType = "arraybuffer"; +oReq.send();</pre> + +<p>更多的範例可參考<a href="/docs/DOM/XMLHttpRequest/Sending_and_Receiving_Binary_Data">傳送及接收二進位資料</a>頁面。</p> + +<h2 id="監視進度">監視進度</h2> + +<p><code>XMLHttpRequest</code> 提供了監聽請求於處理過程中所發生的各項事件之能力。包括了定期進度通知、錯誤通知等等。</p> + +<p><code>XMLHttpRequest</code> 支援可監視其傳輸進度的 DOM 進度事件,此事件遵循<a href="https://xhr.spec.whatwg.org/#interface-progressevent">進度事件規範</a>:這些事件實作了 {{domxref("ProgressEvent")}} 介面。</p> + +<pre class="brush:js">var oReq = new XMLHttpRequest(); + +oReq.addEventListener("progress", updateProgress); +oReq.addEventListener("load", transferComplete); +oReq.addEventListener("error", transferFailed); +oReq.addEventListener("abort", transferCanceled); + +oReq.open(); + +// ... + +// progress on transfers from the server to the client (downloads) +function updateProgress (oEvent) { + if (oEvent.lengthComputable) { + var percentComplete = oEvent.loaded / oEvent.total; + // ... + } else { + // Unable to compute progress information since the total size is unknown + } +} + +function transferComplete(evt) { + console.log("The transfer is complete."); +} + +function transferFailed(evt) { + console.log("An error occurred while transferring the file."); +} + +function transferCanceled(evt) { + console.log("The transfer has been canceled by the user."); +}</pre> + +<p>第 3-6 行加入了事件監聽器來處理使用 <code>XMLHttpRequest</code> 執行資料收發過程中的各類事件。</p> + +<div class="note"><strong>備註:</strong>必須在呼叫 <code>open()</code> 方法開啟請求連線之前就註冊好事件監聽器,否則 <code>progress</code> 事件將不會被觸發。</div> + +<p>在這個例子中,指定了 <code>updateProgress()</code> 函式作為 <code>progress</code> 事件處理器,<code>progress</code> 事件處理器會於 <code>progress</code> 事件物件的 <code>total</code> 及 <code>loaded</code> 屬性分別接收到要傳輸的總位元數及已送出的位元數。然而,假如 <code>lengthComputable</code> 屬性值為假,則代表要傳輸的總位元數是未知且 <code>total</code> 屬性值將會為零。</p> + +<p><code>progress</code> 事件同時存在於上傳及下載傳輸中。下載的相關事件會於 <code>XMLHttpRequest</code> 物件自己身上被觸發,如上面的範例。而上傳相關事件則在 <code>XMLHttpRequest.upload</code> 物件上被觸發,如以下範例:</p> + +<pre class="brush:js">var oReq = new XMLHttpRequest(); + +oReq.upload.addEventListener("progress", updateProgress); +oReq.upload.addEventListener("load", transferComplete); +oReq.upload.addEventListener("error", transferFailed); +oReq.upload.addEventListener("abort", transferCanceled); + +oReq.open(); +</pre> + +<div class="note"><strong>備註:</strong><code>progress</code> 事件無法用於 <code>file:</code> 通訊協定。</div> + +<div class="note"> +<p><strong>備註:</strong>自 {{Gecko("9.0")}} 開始,接收到每一個資料的區塊(chunk)時,<code>progress</code> 事件都會被觸發。包括在 <code>progress</code> 事件被觸發前,就已經接收到含有最後一個資料區塊的最後一個封包並且關閉連線的狀況下,在載入此封包時仍會自動觸發 <code>progress</code> 事件。這代表我們可以僅關注 <code>progress</code> 事件即能夠可靠的監視進度。</p> +</div> + +<div class="note"> +<p><strong>備註:</strong>在 {{Gecko("12.0")}} 中,如果 <code>XMLHttpRequest</code> 的 <code>responseType</code> 屬性為「moz-blob」,那麼 <code>progress</code> 事件觸發時的 <code>XMLHttpRequest.response</code> 值會是一個目前包含了所接收資料的 {{domxref("Blob")}}。</p> +</div> + +<p>我們也可以透過 <code>loadend</code> 事件來偵測到所有之三種下載結束狀況(<code>abort</code>、<code>load</code> 或 <code>error</code>):</p> + +<pre class="brush:js">req.addEventListener("loadend", loadEnd); + +function loadEnd(e) { + console.log("The transfer finished (although we don't know if it succeeded or not)."); +} +</pre> + +<p>請注意由 <code>loadend</code> 事件中接收到的資訊並無法確定是由何種結束狀況所觸發。不過還是可以用 <code>loadend</code> 事件來處理所有傳輸結束情況下需要執行的任務。</p> + +<h2 id="提交表單與上傳檔案">提交表單與上傳檔案</h2> + +<p><code>XMLHttpRequest</code> 物件實體有兩種方式來提交表單:</p> + +<ul> + <li>僅使用 AJAX</li> + <li>使用 {{domxref("XMLHttpRequest.FormData", "FormData")}} API</li> +</ul> + +<p>使用 <code>FormData</code> API 是最簡單、快速的方式,但不利於將資料集合進行<a href="/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify">字串化</a>。<br> + 只使用 AJAX 的方式較為複雜,但也更加靈活、強大。</p> + +<h3 id="僅使用_XMLHttpRequest">僅使用 <code>XMLHttpRequest</code></h3> + +<p>以不透過 <code>FormData</code> API 提交表單的方式在大多數的情況下都不需要使用其他額外的 API。唯一的例外是<strong>要上傳一或多個檔案</strong>時,會需要用到 {{domxref("FileReader")}} API。</p> + +<h4 id="提交方法簡介">提交方法簡介</h4> + +<p>一個 HTML {{HTMLElement("form", "表單(form)")}}有以下四種提交方式:</p> + +<ul> + <li>使用 <code>POST</code> 方法,並且設定 <code>enctype</code> 屬性({{Glossary("attribute")}})為 <code>application/x-www-form-urlencoded</code>(預設值)。</li> + <li>使用 <code>POST</code> 方法,並且設定 <code>enctype</code> 屬性為 <code>text/plain</code>。</li> + <li>使用 <code>POST</code> 方法,並且設定 <code>enctype</code> 屬性為 <code>multipart/form-data</code>。</li> + <li>使用 <code>GET</code> 方法(在此情況下,<code>enctype</code> 屬性將會被忽略)。</li> +</ul> + +<p>現在,假設要提交一個只包含兩個欄位的表單,欄位名稱為 <code>foo</code> 及 <code>baz</code>。若是使用 <code>POST</code> 方法,伺服器將會收到一個如以下三個例子之一的字串,這取決於所使用的編碼類型(encoding type):</p> + +<ul> + <li> + <p>方法:<code>POST</code>;編碼類型:<code>application/x-www-form-urlencoded</code>(預設值):</p> + + <pre class="brush:plain">Content-Type: application/x-www-form-urlencoded + +foo=bar&baz=The+first+line.%0D%0AThe+second+line.%0D%0A</pre> + </li> + <li> + <p>方法:<code>POST</code>;編碼類型:<code>text/plain</code>:</p> + + <pre class="brush:plain">Content-Type: text/plain + +foo=bar +baz=The first line. +The second line.</pre> + </li> + <li> + <p>方法:<code>POST</code>;編碼類型:<code><a href="/docs/Web/HTTP/Basics_of_HTTP/MIME_types#multipartform-data">multipart/form-data</a></code>:</p> + + <pre class="brush:plain">Content-Type: multipart/form-data; boundary=---------------------------314911788813839 + +-----------------------------314911788813839 +Content-Disposition: form-data; name="foo" + +bar +-----------------------------314911788813839 +Content-Disposition: form-data; name="baz" + +The first line. +The second line. + +-----------------------------314911788813839--</pre> + </li> +</ul> + +<p>如果是使用 <code>GET</code> 方法,一個如下方的字串會被直接附加入到 URL 上:</p> + +<pre class="brush:plain">?foo=bar&baz=The%20first%20line.%0AThe%20second%20line.</pre> + +<h4 id="小型原生框架">小型原生框架</h4> + +<p>在我們提交 {{HTMLElement("form")}} 時,瀏覽器自動幫我們做了上面這些工作。假如要使用 JavaScript 達到同樣的效果就必須告訴直譯器(interpreter)要處理的<em>所有事</em>。然而,如何透過<em>純粹的</em> AJAX 來傳送表單複雜到難以在本頁解釋所有細節。基於這個理由,我們改為在這此提供<strong>一組完整(教學用)的框架</strong>,可用於上述四種的每一種<em>提交(submit)</em>,並包括<strong>上傳檔案</strong>:</p> + +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> +<pre class="brush: html"><!doctype html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<title>Sending forms with pure AJAX &ndash; MDN</title> +<script type="text/javascript"> + +"use strict"; + +/*\ +|*| +|*| :: XMLHttpRequest.prototype.sendAsBinary() Polyfill :: +|*| +|*| https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#sendAsBinary() +\*/ + +if (!XMLHttpRequest.prototype.sendAsBinary) { + XMLHttpRequest.prototype.sendAsBinary = function(sData) { + var nBytes = sData.length, ui8Data = new Uint8Array(nBytes); + for (var nIdx = 0; nIdx < nBytes; nIdx++) { + ui8Data[nIdx] = sData.charCodeAt(nIdx) & 0xff; + } + /* send as ArrayBufferView...: */ + this.send(ui8Data); + /* ...or as ArrayBuffer (legacy)...: this.send(ui8Data.buffer); */ + }; +} + +/*\ +|*| +|*| :: AJAX Form Submit Framework :: +|*| +|*| https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest +|*| +|*| This framework is released under the GNU Public License, version 3 or later. +|*| https://www.gnu.org/licenses/gpl-3.0-standalone.html +|*| +|*| Syntax: +|*| +|*| AJAXSubmit(HTMLFormElement); +\*/ + +var AJAXSubmit = (function () { + + function ajaxSuccess () { + /* console.log("AJAXSubmit - Success!"); */ + console.log(this.responseText); + /* you can get the serialized data through the "submittedData" custom property: */ + /* console.log(JSON.stringify(this.submittedData)); */ + } + + function submitData (oData) { + /* the AJAX request... */ + var oAjaxReq = new XMLHttpRequest(); + oAjaxReq.submittedData = oData; + oAjaxReq.onload = ajaxSuccess; + if (oData.technique === 0) { + /* method is GET */ + oAjaxReq.open("get", oData.receiver.replace(/(?:\?.*)?$/, + oData.segments.length > 0 ? "?" + oData.segments.join("&") : ""), true); + oAjaxReq.send(null); + } else { + /* method is POST */ + oAjaxReq.open("post", oData.receiver, true); + if (oData.technique === 3) { + /* enctype is multipart/form-data */ + var sBoundary = "---------------------------" + Date.now().toString(16); + oAjaxReq.setRequestHeader("Content-Type", "multipart\/form-data; boundary=" + sBoundary); + oAjaxReq.sendAsBinary("--" + sBoundary + "\r\n" + + oData.segments.join("--" + sBoundary + "\r\n") + "--" + sBoundary + "--\r\n"); + } else { + /* enctype is application/x-www-form-urlencoded or text/plain */ + oAjaxReq.setRequestHeader("Content-Type", oData.contentType); + oAjaxReq.send(oData.segments.join(oData.technique === 2 ? "\r\n" : "&")); + } + } + } + + function processStatus (oData) { + if (oData.status > 0) { return; } + /* the form is now totally serialized! do something before sending it to the server... */ + /* doSomething(oData); */ + /* console.log("AJAXSubmit - The form is now serialized. Submitting..."); */ + submitData (oData); + } + + function pushSegment (oFREvt) { + this.owner.segments[this.segmentIdx] += oFREvt.target.result + "\r\n"; + this.owner.status--; + processStatus(this.owner); + } + + function plainEscape (sText) { + /* How should I treat a text/plain form encoding? + What characters are not allowed? this is what I suppose...: */ + /* "4\3\7 - Einstein said E=mc2" ----> "4\\3\\7\ -\ Einstein\ said\ E\=mc2" */ + return sText.replace(/[\s\=\\]/g, "\\$&"); + } + + function SubmitRequest (oTarget) { + var nFile, sFieldType, oField, oSegmReq, oFile, bIsPost = oTarget.method.toLowerCase() === "post"; + /* console.log("AJAXSubmit - Serializing form..."); */ + this.contentType = bIsPost && oTarget.enctype ? oTarget.enctype : "application\/x-www-form-urlencoded"; + this.technique = bIsPost ? + this.contentType === "multipart\/form-data" ? 3 : this.contentType === "text\/plain" ? 2 : 1 : 0; + this.receiver = oTarget.action; + this.status = 0; + this.segments = []; + var fFilter = this.technique === 2 ? plainEscape : escape; + for (var nItem = 0; nItem < oTarget.elements.length; nItem++) { + oField = oTarget.elements[nItem]; + if (!oField.hasAttribute("name")) { continue; } + sFieldType = oField.nodeName.toUpperCase() === "INPUT" ? oField.getAttribute("type").toUpperCase() : "TEXT"; + if (sFieldType === "FILE" && oField.files.length > 0) { + if (this.technique === 3) { + /* enctype is multipart/form-data */ + for (nFile = 0; nFile < oField.files.length; nFile++) { + oFile = oField.files[nFile]; + oSegmReq = new FileReader(); + /* (custom properties:) */ + oSegmReq.segmentIdx = this.segments.length; + oSegmReq.owner = this; + /* (end of custom properties) */ + oSegmReq.onload = pushSegment; + this.segments.push("Content-Disposition: form-data; name=\"" + + oField.name + "\"; filename=\"" + oFile.name + + "\"\r\nContent-Type: " + oFile.type + "\r\n\r\n"); + this.status++; + oSegmReq.readAsBinaryString(oFile); + } + } else { + /* enctype is application/x-www-form-urlencoded or text/plain or + method is GET: files will not be sent! */ + for (nFile = 0; nFile < oField.files.length; + this.segments.push(fFilter(oField.name) + "=" + fFilter(oField.files[nFile++].name))); + } + } else if ((sFieldType !== "RADIO" && sFieldType !== "CHECKBOX") || oField.checked) { + /* NOTE: this will submit _all_ submit buttons. Detecting the correct one is non-trivial. */ + /* field type is not FILE or is FILE but is empty */ + this.segments.push( + this.technique === 3 ? /* enctype is multipart/form-data */ + "Content-Disposition: form-data; name=\"" + oField.name + "\"\r\n\r\n" + oField.value + "\r\n" + : /* enctype is application/x-www-form-urlencoded or text/plain or method is GET */ + fFilter(oField.name) + "=" + fFilter(oField.value) + ); + } + } + processStatus(this); + } + + return function (oFormElement) { + if (!oFormElement.action) { return; } + new SubmitRequest(oFormElement); + }; + +})(); + +</script> +</head> +<body> + +<h1>Sending forms with pure AJAX</h1> + +<h2>Using the GET method</h2> + +<form action="register.php" method="get" onsubmit="AJAXSubmit(this); return false;"> + <fieldset> + <legend>Registration example</legend> + <p> + First name: <input type="text" name="firstname" /><br /> + Last name: <input type="text" name="lastname" /> + </p> + <p> + <input type="submit" value="Submit" /> + </p> + </fieldset> +</form> + +<h2>Using the POST method</h2> +<h3>Enctype: application/x-www-form-urlencoded (default)</h3> + +<form action="register.php" method="post" onsubmit="AJAXSubmit(this); return false;"> + <fieldset> + <legend>Registration example</legend> + <p> + First name: <input type="text" name="firstname" /><br /> + Last name: <input type="text" name="lastname" /> + </p> + <p> + <input type="submit" value="Submit" /> + </p> + </fieldset> +</form> + +<h3>Enctype: text/plain</h3> + +<form action="register.php" method="post" enctype="text/plain" + onsubmit="AJAXSubmit(this); return false;"> + <fieldset> + <legend>Registration example</legend> + <p> + Your name: <input type="text" name="user" /> + </p> + <p> + Your message:<br /> + <textarea name="message" cols="40" rows="8"></textarea> + </p> + <p> + <input type="submit" value="Submit" /> + </p> + </fieldset> +</form> + +<h3>Enctype: multipart/form-data</h3> + +<form action="register.php" method="post" enctype="multipart/form-data" + onsubmit="AJAXSubmit(this); return false;"> + <fieldset> + <legend>Upload example</legend> + <p> + First name: <input type="text" name="firstname" /><br /> + Last name: <input type="text" name="lastname" /><br /> + Sex: + <input id="sex_male" type="radio" name="sex" value="male" /> + <label for="sex_male">Male</label> + <input id="sex_female" type="radio" name="sex" value="female" /> + <label for="sex_female">Female</label><br /> + Password: <input type="password" name="secret" /><br /> + What do you prefer: + <select name="image_type"> + <option>Books</option> + <option>Cinema</option> + <option>TV</option> + </select> + </p> + <p> + Post your photos: + <input type="file" multiple name="photos[]"> + </p> + <p> + <input id="vehicle_bike" type="checkbox" name="vehicle[]" value="Bike" /> + <label for="vehicle_bike">I have a bike</label><br /> + <input id="vehicle_car" type="checkbox" name="vehicle[]" value="Car" /> + <label for="vehicle_car">I have a car</label> + </p> + <p> + Describe yourself:<br /> + <textarea name="description" cols="50" rows="8"></textarea> + </p> + <p> + <input type="submit" value="Submit" /> + </p> + </fieldset> +</form> + +</body> +</html></pre> +</div> + +<p>為了進行測試,建立一個名為 <strong>register.php</strong> 的 PHP 頁面(即為上面範例表單之 <code>action</code> 屬性({{Glossary("attribute")}})所指向的位置),並輸入以下<em>最簡化</em>的內容:</p> + +<pre class="brush: php"><?php +/* register.php */ + +header("Content-type: text/plain"); + +/* +NOTE: You should never use `print_r()` in production scripts, or +otherwise output client-submitted data without sanitizing it first. +Failing to sanitize can lead to cross-site scripting vulnerabilities. +*/ + +echo ":: data received via GET ::\n\n"; +print_r($_GET); + +echo "\n\n:: Data received via POST ::\n\n"; +print_r($_POST); + +echo "\n\n:: Data received as \"raw\" (text/plain encoding) ::\n\n"; +if (isset($HTTP_RAW_POST_DATA)) { echo $HTTP_RAW_POST_DATA; } + +echo "\n\n:: Files received ::\n\n"; +print_r($_FILES); + +</pre> + +<p>使用這個框架的語法簡單如下:</p> + +<pre class="syntaxbox">AJAXSubmit(myForm);</pre> + +<div class="note"><strong>備註:</strong>此框架使用了 {{domxref("FileReader")}} API 來發送檔案上傳。這是個較新的 API,且 IE9 或其先前版本並未實作。因為這個理由,AJAX-only 上傳被認為是<strong>一項實驗性技術</strong>。若沒有需要上傳二進位檔案,此框架可於大部分瀏覽器中運作良好。</div> + +<div class="note"><strong>備註:</strong>傳送二進位檔案的最佳方式是藉由 {{jsxref("ArrayBuffer", "ArrayBuffers")}} 或 {{domxref("Blob", "Blobs")}} 結合 {{domxref("XMLHttpRequest.send()", "send()")}} 方法來送出,如果可以也能搭配 <code>FileReader</code> API 的 {{domxref("FileReader.readAsArrayBuffer()", "readAsArrayBuffer()")}} 方法先進行讀取。但因為這段程式指令碼(script)的目的是要處理<a href="/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify">可字串化的</a>原始資料,所以使用 {{domxref("XMLHttpRequest.sendAsBinary()", "sendAsBinary()")}} 方法結合 <code>FileReader</code> API 的 {{domxref("FileReader.readAsBinaryString()", "readAsBinaryString()")}} 方法。就其本身來看,以上的指令碼只有在處理小型檔案時才有意義。假如不打算上傳二進位內容,請考慮使用 <code>FormData</code> API。</div> + +<div class="note"><strong>備註:</strong>非標準的 <code>sendAsBinary</code> 方法在 Gecko 31 {{geckoRelease(31)}} 已被認為是棄用的(deprecated),並且即將被移除。而標準的 <code>send(Blob data)</code> 方法可以作為替代。</div> + +<h3 id="使用_FormData_物件">使用 FormData 物件</h3> + +<p>{{domxref("XMLHttpRequest.FormData", "FormData")}} 建構式可以讓我們收集一連串名/值對資料並透過 <code>XMLHttpRequest</code> 送出。其主要用於傳送表單資料,但也能夠單獨的由表單建立來傳輸使用者輸入的資料。若表單的編碼類型(encoding type)被設定為「multipart/form-data」,則由 <code>FormData</code> 所發送的資料格式和表單用來傳送資料的 <code>submit()</code> 方法相同。FormData 物件可以搭配 <code>XMLHttpRequest</code> 以多種方式使用。相關的範例,以及可以怎麼利用 FormData 配合 XMLHttpRequest 的說明,請參考<a href="/docs/DOM/XMLHttpRequest/FormData/Using_FormData_Objects">使用 FormData 物件</a>頁面。為了教學使用,下方為<strong>一個利用 <code>FormData</code> API 來改寫<a href="#小型原生框架">先前範例</a>的<em>翻譯</em>版本</strong>。注意這段精簡後的程式碼:</p> + +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> +<pre class="brush: html"><!doctype html> +<html> +<head> +<meta http-equiv="Content-Type" charset="UTF-8" /> +<title>Sending forms with FormData &ndash; MDN</title> +<script> +"use strict"; + +function ajaxSuccess () { + console.log(this.responseText); +} + +function AJAXSubmit (oFormElement) { + if (!oFormElement.action) { return; } + var oReq = new XMLHttpRequest(); + oReq.onload = ajaxSuccess; + if (oFormElement.method.toLowerCase() === "post") { + oReq.open("post", oFormElement.action); + oReq.send(new FormData(oFormElement)); + } else { + var oField, sFieldType, nFile, sSearch = ""; + for (var nItem = 0; nItem < oFormElement.elements.length; nItem++) { + oField = oFormElement.elements[nItem]; + if (!oField.hasAttribute("name")) { continue; } + sFieldType = oField.nodeName.toUpperCase() === "INPUT" ? + oField.getAttribute("type").toUpperCase() : "TEXT"; + if (sFieldType === "FILE") { + for (nFile = 0; nFile < oField.files.length; + sSearch += "&" + escape(oField.name) + "=" + escape(oField.files[nFile++].name)); + } else if ((sFieldType !== "RADIO" && sFieldType !== "CHECKBOX") || oField.checked) { + sSearch += "&" + escape(oField.name) + "=" + escape(oField.value); + } + } + oReq.open("get", oFormElement.action.replace(/(?:\?.*)?$/, sSearch.replace(/^&/, "?")), true); + oReq.send(null); + } +} +</script> +</head> +<body> + +<h1>Sending forms with FormData</h1> + +<h2>Using the GET method</h2> + +<form action="register.php" method="get" onsubmit="AJAXSubmit(this); return false;"> + <fieldset> + <legend>Registration example</legend> + <p> + First name: <input type="text" name="firstname" /><br /> + Last name: <input type="text" name="lastname" /> + </p> + <p> + <input type="submit" value="Submit" /> + </p> + </fieldset> +</form> + +<h2>Using the POST method</h2> +<h3>Enctype: application/x-www-form-urlencoded (default)</h3> + +<form action="register.php" method="post" onsubmit="AJAXSubmit(this); return false;"> + <fieldset> + <legend>Registration example</legend> + <p> + First name: <input type="text" name="firstname" /><br /> + Last name: <input type="text" name="lastname" /> + </p> + <p> + <input type="submit" value="Submit" /> + </p> + </fieldset> +</form> + +<h3>Enctype: text/plain</h3> + +<p>The text/plain encoding is not supported by the FormData API.</p> + +<h3>Enctype: multipart/form-data</h3> + +<form action="register.php" method="post" enctype="multipart/form-data" + onsubmit="AJAXSubmit(this); return false;"> + <fieldset> + <legend>Upload example</legend> + <p> + First name: <input type="text" name="firstname" /><br /> + Last name: <input type="text" name="lastname" /><br /> + Sex: + <input id="sex_male" type="radio" name="sex" value="male" /> + <label for="sex_male">Male</label> + <input id="sex_female" type="radio" name="sex" value="female" /> + <label for="sex_female">Female</label><br /> + Password: <input type="password" name="secret" /><br /> + What do you prefer: + <select name="image_type"> + <option>Books</option> + <option>Cinema</option> + <option>TV</option> + </select> + </p> + <p> + Post your photos: + <input type="file" multiple name="photos[]"> + </p> + <p> + <input id="vehicle_bike" type="checkbox" name="vehicle[]" value="Bike" /> + <label for="vehicle_bike">I have a bike</label><br /> + <input id="vehicle_car" type="checkbox" name="vehicle[]" value="Car" /> + <label for="vehicle_car">I have a car</label> + </p> + <p> + Describe yourself:<br /> + <textarea name="description" cols="50" rows="8"></textarea> + </p> + <p> + <input type="submit" value="Submit" /> + </p> + </fieldset> +</form> +</body> +</html></pre> +</div> + +<div class="note"><strong>備註:</strong>如同之前所說,<strong>{{domxref("FormData")}} 物件是不能被<a href="/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify">字串化</a>的物件</strong>。若想要字串化一個被提交的資料,請使用<a href="#小型原生框架">先前的<em>純</em> AJAX 範例</a>。還要注意的是,雖然在這個例子中有一些 <code>file</code> {{ HTMLElement("input") }} 欄位,<strong>當你透過 <code>FormData</code> API 來提交表單便也不需要使用 {{domxref("FileReader")}} API</strong>:檔案會自動地載入並上傳。</div> + +<h2 id="取得最後修改日期">取得最後修改日期</h2> + +<pre class="brush: js">function getHeaderTime () { + console.log(this.getResponseHeader("Last-Modified")); /* A valid GMTString date or null */ +} + +var oReq = new XMLHttpRequest(); +oReq.open("HEAD" /* use HEAD if you only need the headers! */, "yourpage.html"); +oReq.onload = getHeaderTime; +oReq.send();</pre> + +<h3 id="當最後修改日期改變時做一些事">當最後修改日期改變時做一些事</h3> + +<p>先建立兩個函式:</p> + +<pre class="brush: js">function getHeaderTime () { + var nLastVisit = parseFloat(window.localStorage.getItem('lm_' + this.filepath)); + var nLastModif = Date.parse(this.getResponseHeader("Last-Modified")); + + if (isNaN(nLastVisit) || nLastModif > nLastVisit) { + window.localStorage.setItem('lm_' + this.filepath, Date.now()); + isFinite(nLastVisit) && this.callback(nLastModif, nLastVisit); + } +} + +function ifHasChanged(sURL, fCallback) { + var oReq = new XMLHttpRequest(); + oReq.open("HEAD" /* use HEAD - we only need the headers! */, sURL); + oReq.callback = fCallback; + oReq.filepath = sURL; + oReq.onload = getHeaderTime; + oReq.send(); +}</pre> + +<p>並進行測試:</p> + +<pre class="brush: js">/* Let's test the file "yourpage.html"... */ + +ifHasChanged("yourpage.html", function (nModif, nVisit) { + console.log("The page '" + this.filepath + "' has been changed on " + (new Date(nModif)).toLocaleString() + "!"); +});</pre> + +<p>如果想要知道<strong><em>目前頁面</em><em>是否</em>已變更</strong>,請參考 {{domxref("document.lastModified")}} 一文。</p> + +<h2 id="跨網域_XMLHttpRequest">跨網域 XMLHttpRequest</h2> + +<p>現代瀏覽器支援跨網域(cross-site)請求並實作了網路應用程式工作小組(Web Applications (WebApps) Working Group)提出的<a href="/docs/Web/HTTP/Access_control_CORS">跨網域請求存取控制</a>標準。只要伺服器被設定為允許來自你的網路應用程式來源(origin)網域之請求,<code>XMLHttpRequest</code> 便能正常運作。否則,將會拋出一個 <code>INVALID_ACCESS_ERR</code> 例外。</p> + +<h2 id="避開快取">避開快取</h2> + +<p>有一個跨瀏覽器相容的避開快取方法,便是將時間戳記(timestamp)附加於 URL 後方,請確保加上了適當的「?」或「&」。例如:</p> + +<pre class="brush:plain">http://foo.com/bar.html -> http://foo.com/bar.html?12345 +http://foo.com/bar.html?foobar=baz -> http://foo.com/bar.html?foobar=baz&12345 +</pre> + +<p>由於本地快取的索引是基於 URL,加入時間戳記會導致每一個請求都會是唯一的,藉此避開快取。</p> + +<p>可以使用以下的程式碼來自動的調整 URL:</p> + +<pre class="brush:js">var oReq = new XMLHttpRequest(); + +oReq.open("GET", url + ((/\?/).test(url) ? "&" : "?") + (new Date()).getTime()); +oReq.send(null);</pre> + +<h2 id="安全性">安全性</h2> + +<p>{{fx_minversion_note(3, "Firefox 3 之前的版本允許在偏好設定中設定 <code>capability.policy.<policyname>.XMLHttpRequest.open</policyname></code> 為 <code>allAccess</code> 來讓指定的網域能夠跨網域存取。現已不再支援。")}}</p> + +<p>{{fx_minversion_note(5, "Firefox 5 之前的版本可以使用 <code>netscape.security.PrivilegeManager.enablePrivilege(\"UniversalBrowserRead\");</code> 來發送跨網域存取請求。現已不再支援,即使它不會有警告並且依然會顯示允許請求的權限對話框。")}}</p> + +<p>開啟跨網域指令碼(script)的建議方式是於 XMLHttpRequest 的回應中使用 <code>Access-Control-Allow-Origin</code> HTTP 標頭。</p> + +<h3 id="被中止的_XMLHttpRequest">被中止的 XMLHttpRequest</h3> + +<p>如果你發現 <code>XMLHttpRequest</code> 的 <code>status=0</code> 且 <code>statusText=null</code>,這代表請求並不被允許執行,其狀態為 <code><a href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-unsent">UNSENT(未送出)</a></code>。被中止的原因可能是因為 <a href="https://www.w3.org/TR/2010/CR-XMLHttpRequest-20100803/#xmlhttprequest-origin"><code>XMLHttpRequest</code> 物件所關聯的 origin(來源網域)值</a>(於 <code>XMLHttpRequest</code> 物件建立時自 <code>window.origin</code> 取得)在呼叫 <code>open()</code> 方法之前就已經被改變。這是可能發生的,例如在 <code>window</code> 的 <code>onunload</code> 事件觸發時送出 <code>XMLHttpRequest</code> 請求,預期的情況為:<code>XMLHttpRequest</code> 物件剛被建立,而目前的視窗尚未關閉,而最後發送請求(即呼叫了 <code>open()</code> 方法)的時間點是在此視窗失去了焦點並且另外的視窗取得焦點之間。要避開這個問題的最有效方法是在要被終止的(terminated)<code>window</code> 觸發 <code>unload</code> 事件時,於新的 <code>window</code> 的上註冊一個新的 <code>activate</code> 事件監聽器來發送請求。</p> + +<h2 id="使用_JavaScript_模組/XPCOM_元件中的_XMLHttpRequest">使用 JavaScript 模組/XPCOM 元件中的 XMLHttpRequest</h2> + +<p>自 <a href="/docs/Mozilla/JavaScript_code_modules/Using">JavaScript 模組</a> 或 XPCOM 元件實體化一個 <code>XMLHttpRequest</code> 物件在做法上會有些許不同;我們無法用 <code>XMLHttpRequest()</code> 建構式,因為此建構式並未在元件中定義,並會導致程式產生錯誤。較佳的方式是使用 XPCOM 元件的建構式。</p> + +<pre class="brush: js">const XMLHttpRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1", + "nsIXMLHttpRequest"); +</pre> + +<p>在 Gecko 16 之前,存在著一個透過這種方式發送的請求會被無條件取消的臭蟲。若程式需要在 Gecko 15 或更早的版本上運作,可以從隱藏的 DOM window 中取得 <code>XMLHttpRequest()</code> 建構式。</p> + +<pre class="brush:js">const { XMLHttpRequest } = Components.classes["@mozilla.org/appshell/appShellService;1"] + .getService(Components.interfaces.nsIAppShellService) + .hiddenDOMWindow; +var oReq = new XMLHttpRequest();</pre> + +<h2 id="參見">參見</h2> + +<ol> + <li><a href="/docs/AJAX/Getting_Started">MDN AJAX 介紹</a></li> + <li><a href="/docs/Web/HTTP/Access_control_CORS">HTTP 存取控制</a></li> + <li><a href="/docs/How_to_check_the_security_state_of_an_XMLHTTPRequest_over_SSL">How to check the security state of an XMLHTTPRequest over SSL</a></li> + <li><a href="http://www.peej.co.uk/articles/rich-user-experience.html">XMLHttpRequest - REST and the Rich User Experience</a></li> + <li><a href="https://msdn.microsoft.com/library/ms535874">Microsoft documentation</a></li> + <li><a href="https://developer.apple.com/library/safari/documentation/AppleApplications/Conceptual/SafariJSProgTopics/Articles/XHR.html">Apple developers' reference</a></li> + <li><a href="http://jibbering.com/2002/4/httprequest.html">"Using the XMLHttpRequest Object" (jibbering.com)</a></li> + <li><a href="https://xhr.spec.whatwg.org/">The <code>XMLHttpRequest</code> object: WHATWG specification</a></li> +</ol> diff --git a/files/zh-tw/web/api/xmlhttprequest/withcredentials/index.html b/files/zh-tw/web/api/xmlhttprequest/withcredentials/index.html new file mode 100644 index 0000000000..e70f611ece --- /dev/null +++ b/files/zh-tw/web/api/xmlhttprequest/withcredentials/index.html @@ -0,0 +1,48 @@ +--- +title: XMLHttpRequest.withCredentials +slug: Web/API/XMLHttpRequest/withCredentials +translation_of: Web/API/XMLHttpRequest/withCredentials +--- +<div>{{APIRef('XMLHttpRequest')}}</div> + +<p><code><strong>XMLHttpRequest.withCredentials</strong></code> 屬性是一個 {{jsxref("Boolean")}} 型別,它指出無論是否使用 <code>Access-Control</code> 標頭在跨站的要求上,都應該使用像 Cookies、Authorization 標頭或 TLS 用戶端憑證來進行驗證。在相同來源的要求設定 <code>withCredentials</code> 沒有任何效果。</p> + +<p>In addition, this flag is also used to indicate when cookies are to be ignored in the response. The default is <code>false</code>. <code>XMLHttpRequest</code> from a different domain cannot set cookie values for their own domain unless <code>withCredentials</code> is set to <code>true</code> before making the request. The third-party cookies obtained by setting <code>withCredentials</code> to true will still honor same-origin policy and hence can not be accessed by the requesting script through <a href="/en-US/docs/Web/API/Document/cookie">document.cookie</a> or from response headers.</p> + +<div class="note"> +<p><strong>Note:</strong> 永遠不會影響到同源請求。</p> +</div> + +<div class="note"> +<p><strong>Note:</strong><strong> </strong><code>XMLHttpRequest</code> responses from a different domain <em>cannot</em> set cookie values for their own domain unless <code>withCredentials</code> is set to <code>true</code> before making the request, regardless of <code>Access-Control-</code> header values. </p> +</div> + +<h2 id="範例">範例</h2> + +<pre class="brush: js">var xhr = new XMLHttpRequest(); +xhr.open('GET', 'http://example.com/', true); +xhr.withCredentials = true; +xhr.send(null);</pre> + +<h2 id="規格">規格</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">規格</th> + <th scope="col">狀態</th> + <th scope="col">備註</th> + </tr> + <tr> + <td>{{SpecName('XMLHttpRequest', '#the-withcredentials-attribute')}}</td> + <td>{{Spec2('XMLHttpRequest')}}</td> + <td>WHATWG living standard</td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + + + +<p>{{Compat("api.XMLHttpRequest.withCredentials")}}</p> diff --git a/files/zh-tw/web/api/xmlhttprequest/xmlhttprequest/index.html b/files/zh-tw/web/api/xmlhttprequest/xmlhttprequest/index.html new file mode 100644 index 0000000000..6459ef0c2a --- /dev/null +++ b/files/zh-tw/web/api/xmlhttprequest/xmlhttprequest/index.html @@ -0,0 +1,50 @@ +--- +title: XMLHttpRequest() +slug: Web/API/XMLHttpRequest/XMLHttpRequest +translation_of: Web/API/XMLHttpRequest/XMLHttpRequest +--- +<div>{{draft}}{{APIRef('XMLHttpRequest')}}</div> + +<p><span class="seoSummary"><code><strong>XMLHttpRequest()</strong></code> 建構式會建立一個新的 {{domxref("XMLHttpRequest")}} 物件。</span></p> + +<p>關於如何使用 <code>XMLHttpRequest</code> 物件的細節,請參照: <a class="internal" href="/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest">Using XMLHttpRequest</a>.</p> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox">const <var>request</var> = new XMLHttpRequest(); +</pre> + +<h3 id="參數">參數</h3> + +<p>無。</p> + +<h3 id="回傳值">回傳值 </h3> + +<p>將回傳一個新的 {{domxref("XMLHttpRequest")}} 物件。{{domxref("XMLHttpRequest")}} 物件在呼叫{{domxref("XMLHttpRequest.send", "send()")}} 送出要求到伺服器之前,至少要藉著呼叫 {{domxref("XMLHttpRequest.open", "open()")}} 來準備好必需的設定。</p> + +<h2 id="非標準的_Firefox_語法">非標準的 Firefox 語法</h2> + +<p>Firefox 16 added a non-standard parameter to the constructor that can enable anonymous mode (see {{Bug("692677")}}). Setting the <code>mozAnon</code> flag to <code>true</code> effectively resembles the <a href="http://www.w3.org/TR/2012/WD-XMLHttpRequest-20120117/#dom-anonxmlhttprequest" title="see AnonXMLHttpRequest in the XMLHttpRequest specification"><code>AnonXMLHttpRequest()</code></a> constructor described in older versions of the XMLHttpRequest specification.</p> + +<pre class="syntaxbox">const <var>request</var> = new XMLHttpRequest(<var>paramsDictionary</var>);</pre> + +<h3 id="Parameters_non-standard">Parameters (non-standard)</h3> + +<dl> + <dt><code>objParameters</code> {{gecko_minversion_inline("16.0")}}</dt> + <dd>There are two flags you can set: + <dl> + <dt><code>mozAnon</code></dt> + <dd>Boolean: Setting this flag to <code>true</code> will cause the browser not to expose the {{Glossary("origin")}} and <a href="http://www.w3.org/TR/2012/WD-XMLHttpRequest-20120117/#user-credentials" title="Defintion of “User credentials” in the XMLHttpRequest specification.">user credentials</a> when fetching resources. Most important, this means that {{Glossary("Cookie", "cookies")}} will not be sent unless explicitly added using setRequestHeader.</dd> + <dt><code>mozSystem</code></dt> + <dd>Boolean: Setting this flag to <code>true</code> allows making cross-site connections without requiring the server to opt-in using {{Glossary("CORS")}}. <em>Requires setting <code>mozAnon: true</code>, i.e. this can't be combined with sending cookies or other user credentials. This only works in privileged (reviewed) apps ({{Bug("692677")}}); it does not work on arbitrary webpages loaded in Firefox</em></dd> + </dl> + </dd> +</dl> + +<h2 id="參見">參見</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest">Using XMLHttpRequest</a></li> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest/HTML_in_XMLHttpRequest">HTML in XMLHttpRequest</a></li> +</ul> |