`

Using XMLHttpRequest

阅读更多

XMLHttpRequest makes sending HTTP requests very easy. You simply create an instance of the object, open a URL, and send the request. The HTTPstatus of the result, as well as the result's contents, are available in the request object when the transaction is completed.

Synchronous and asynchronous requests

XMLHttpRequest supports both synchronous and asynchronous communications.

Note: You shouldn't use synchronous XMLHttpRequests because, due to the inherently asynchronous nature of networking, there are various ways memory and events can leak when using synchronous requests.

In versions of Firefox prior to Firefox 3, synchronous XMLHttpRequest requests blocked the user interface. In order to make it possible for the user to terminate frozen requests, Firefox 3 no longer does so.

Example:Synchronous request

This example demonstrates how to make a simple synchronous request.

1 var req = new XMLHttpRequest();
2 req.open( 'GET' , 'http://www.mozilla.org/ ' , false );
3 req.send( null );
4 if (req.status == 200)
5 dump(req.responseText);

Line 1 instantiates the XMLHttpRequest object. Line 2 then opens a new request, specifying that a GET request will be used to fetch the Mozilla.org home page, and that the operation should not be asynchronous.

Line 3 sends the request. The null parameter indicates that no body content is needed for the GET request.

Line 4 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.

Example:Non-HTTP synchronous request

Despite its name, XMLHttpRequest can be used for non-HTTPrequests. This example shows how to use it to fetch a file from the local file system.

1 var req = new XMLHttpRequest();
2 req.open( 'GET' , 'file:///home/user/file.json ' , false );
3 req.send( null );
4 if (req.status == 0)
5 dump(req.responseText);

The key thing to note here is that the result status is being compared to 0 for success instead of 200. This is because the file and ftp schemes do not use HTTPresult codes.

Example: Asynchronous request

If you use XMLHttpRequest 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.

01 var req = new XMLHttpRequest();
02 req.open( 'GET' , 'http://www.mozilla.org/ ' , true );
03 req.onreadystatechange = function (aEvt) {
04 if (req.readyState == 4) {
05 if (req.status == 200)
06 dump(req.responseText);
07 else
08 dump( "Error loading page\n" );
09 }
10 };
11 req.send( null );

Line 2 specifies true for its third parameter to indicate that the request should be handled asynchronously.

Line 3 creates an event handler function object and assigns it to the request's onreadystatechange attribute. This handler looks at the request's readyState to see if the transaction is complete in line 4, and if it is, and the HTTPstatus is 200, dumps the received content. If an error occurred, an error message is displayed.

Line 11 actually initiates the request. The callback routine is called whenever the state of the request changes.

Analyzing and manipulating HTML responseText

If you use XMLHttpRequest to get the content of a remote HTML webpage, the responseText will be a string containing a "soup" of all the HTML tags, which can be hard to manipulate and analyze. There are three primary ways of analyzing this HTML soup string

  1. Safely parsing with nsIScriptableUnescapeHTML will quickly convert the HTMLstring into DOM, while striping out javascript and other advanced elements, including the <head> of the webpage.
  2. RegExp can be used if you always know the content of the HTML responseText beforehand. You might want to remove line breaks, if you use RegExp to scan with regard to linebreaks. However, this method is a "last resort" since if the HTML code changes slightly, the method will likely fail.
  3. Using a hidden chrome or content-level iframe to load up the webpage can also be done to then manipulate it as DOM, however there are security risks to giving remote code this level of privileged access , which can cause issues for the review of your addon. For example, if a webpage executes the common "document.location = redirecttothispage.html " command on load, this will get interpreted as changing the browser chrome location (document.location in an extension) as opposed to the webpage location (content.document.location in an extension), thus destroying all browser components. Alternatively, and somewhat safer, a responseText string attained through a XMLHttpRequest can be analyzed using RegExp to remove potential JavaScript problems, then loaded into the hidden iframe that you have set up:
document.getElementById('hiddenXULiframe').contentWindow.document.body.innerHTML = req.responseText

Using FormData objects

Introduced in Gecko 2

(Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)

The FormData object lets you compile a set of key/value pairs to send using XMLHttpRequest . It's primarily intended for use in sending form data, but can be used independently from forms in order to transmit keyed data. The transmitted data is in the same format that the form's submit() method would use to send the data if the form's encoding type were set to "multipart/form-data".

Creating a FormData object from scratch

You can build a FormData object yourself, instantiating it then appending fields to it by calling its append() method, like this:

1 var formData = new FormData();
2
3 formData.append( "username" , "Groucho" );
4 formData.append( "accountnum" , 123456);
5 formData.append( "afile" , fileInputElement.files[0]);
6
7 var xhr = new XMLHttpRequest();
8 xhr.open( "POST" , "http://foo.com/submitform.php " );
9 xhr.send(formData);

This example builds a FormData object containing values for fields named "username" and "accountnum", then uses the XMLHttpRequest method send() to send the form's data.

Retrieving a FormData object from anHTMLform

To construct a FormData object that contains the data from an existing <form> , specify that form element when creating the FormData object:

newFormData = new FormData(someFormElement);

For example:

1 var formElement = document.getElementById( "myFormElement" );
2 var xhr = new XMLHttpRequest();
3 xhr.open( "POST" , "submitform.php" );
4 xhr.send( new FormData(formElement));

You can also add data to the FormData object between retrieving it from a form and sending it, like this:

1 var formElement = document.getElementById( "myFormElement" );
2 formData = new FormData(formElement);
3 formData.append( "serialnumber" , serialNumber++);
4 xhr.send(formData);

This lets you augment the form's data before sending it along, to include additional information that's not necessarily user editable on the form.

Sending files using a FormData object

You can also send files using FormData . Simply include an <input> element of type "file":

01 < form enctype = "multipart/form-data" method = "post" name = "fileinfo" id = "fileinfo" >
02 < label >Your email address:</ label >
03 < input type = "email" autocomplete = "on" autofocus name = "userid" placeholder = "email" required size = "32" maxlength = "64" >< br />
04 < label >Custom file ID:</ label >
05 < input type = "text" name = "fileid" size = "12" maxlength = "32" >< br />
06 < label >File to stash:</ label >
07 < input type = "file" name = "file" required>
08 </ form >
09 < div id = "output" ></ div >
10 < a href = "javascript:sendForm()" >Stash the file!</ a >

Then you can send it using code like the following:

01 function sendForm() {
02 var output = document.getElementById( "output" );
03 var data = new FormData(document.getElementById( "fileinfo" ));
04
05 data.append( "CustomField" , "This is some extra data" );
06
07 var xhr = new XMLHttpRequest();
08 xhr.open( "POST" , "stash.pl" , false )
09 xhr.send(data);
10 if (xhr.status == 200) {
11 output.innerHTML += "Uploaded!<br />" ;
12 } else {
13 output.innerHTML += "Error " + xhr.status + " occurred uploading your file.<br />" ;
14 }
15 }

Note that this example is directing the output to a Perl CGI script running on the server, and handles HTTPerrors, although not prettily.

You can also use FormData with jQuery if you set the right options:

1 var fd = new FormData(document.getElementById( "fileinfo" ));
2 fd.append( "CustomField" , "This is some extra data" );
3 $.ajax({
4 url: "stash.pl" ,
5 type: "POST" ,
6 data: fd,
7 processData: false , // tell jQuery not to process the data
8 contentType: false // tell jQuery not to set contentType
9 });

Handling binary data

Although XMLHttpRequest is most commonly used to send and receive textual data, it can be used to send and receive binary content.

Receiving binary data

The load_binary_resource() function shown below loads binary data from the specified URL, returning it to the caller.

1 function load_binary_resource(url) {
2 var req = new XMLHttpRequest();
3 req.open( 'GET' , url, false );
4 //XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com ]
5 req.overrideMimeType( 'text/plain; charset=x-user-defined' );
6 req.send( null );
7 if (req.status != 200) return '' ;
8 return req.responseText;
9 }

The magic happens in line 5, which overrides the MIMEtype, forcing Firefox to treat it as plain text, using a user-defined character set. This tells Firefox not to parse it, and to let the bytes pass through unprocessed.

1 var filestream = load_binary_resource(url);
2 var abyte = filestream.charCodeAt(x) & 0xff; // throw away high-order byte (f7)

The example above fetches the byte at offset x within the loaded binary data. The valid range for x is from 0 to filestream.length-1 .

See downloading binary streams with XMLHttpRequest for a detailed explanation. See also downloading files .

Receiving binary data using JavaScript typed arrays

Introduced in Gecko 2.0

(Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)

Obsolete since Gecko 6 (Firefox 6.0)

Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1) adds a Gecko-specific mozResponseArrayBuffer property to the XMLHttpRequest object, which contains a JavaScript typed array representing the raw binary contents of the response from the server. This lets you read the binary data without taking any special steps.

01 var xhr = new XMLHttpRequest();
02 xhr.open( "GET" , "binary_file" , false );
03 xhr.send( null );
04
05 buffer = xhr.mozResponseArrayBuffer;
06 if (buffer) {
07 var byteArray = new Uint8Array(buffer);
08 for ( var i=0; i<byteArray.byteLength; i++) {
09 // do something with each byte in the array
10 }
11 }

This example reads a binary file and interprets it as 8-bit unsigned integers.

Introduced in Gecko 6

(Firefox 6.0)

Gecko 6 (Firefox 6.0) adds r esponseType and response properties to the XMLHttpRequest object on behalf of the mozResponseArrayBuffer property.

01 var xhr = new XMLHttpRequest();
02 xhr.open( "GET" , "binary_file" , false );
03 xhr.responseType = "arraybuffer" ;
04 xhr.send( null );
05
06 buffer = xhr.response;
07 if (buffer) {
08 var byteArray = new Uint8Array(buffer);
09 for ( var i=0; i<byteArray.byteLength; i++) {
10 // do something with each byte in the array
11 }
12 }

This example reads a binary file and interprets it as 8-bit unsigned integers.

Sending binary data

This example transmits binary content asynchronously, using the POST method.

1 var req = new XMLHttpRequest();
2 req.open( "POST" , url, true );
3 // set headers and mime-type appropriately
4 req.setRequestHeader( "Content-Length" , 741);
5 req.sendAsBinary(aBody);

Line 4 sets the Content-Length header to 741, indicating that the data is 741 bytes long. Obviously you need to change this value based on the actual size of the data being sent.

Line 5 uses the sendAsBinary() method to initiate the request.

You can also send binary content by passing an instance of the nsIFileInputStream to send() . In that case, you don't have to set the Content-Length header yourself, as the information is fetched from the stream automatically:

01 // Make a stream from a file.
02 var stream = Components.classes[ "@mozilla.org/network/file-input-stream;1" ]
03 .createInstance(Components.interfaces.nsIFileInputStream);
04 stream.init(file, 0x04 | 0x08, 0644, 0x04); // file is an nsIFile instance
05
06 // Try to determine the MIME type of the file
07 var mimeType = "text/plain" ;
08 try {
09 var mimeService = Components.classes[ "@mozilla.org/mime;1" ]
10 .getService(Components.interfaces.nsIMIMEService);
11 mimeType = mimeService.getTypeFromFile(file); // file is an nsIFile instance
12 }
13 catch (e) { /* eat it; just use text/plain */ }
14
15 // Send
16 var req = Components.classes[ "@mozilla.org/xmlextras/xmlhttprequest;1" ]
17 .createInstance(Components.interfaces.nsIXMLHttpRequest);
18 req.open( 'PUT' , url, false ); /* synchronous! */
19 req.setRequestHeader( 'Content-Type' , mimeType);
20 req.send(stream);

Monitoring progress

XMLHttpRequest provides the ability to listen to various events that can occur while the request is being processed. This includes periodic progress notifications, error notifications, and so forth.

Requires Gecko 1.9.1 (Firefox 3.5 / Thunderbird 3.0 / SeaMonkey 2.0)

In Firefox 3.5 and later

Gecko 1.9.1 (Firefox 3.5 / Thunderbird 3.0 / SeaMonkey 2.0) adds support for DOM progress event monitoring of XMLHttpRequest transfers; this follows the Web API specification for progress events .

01 var req = new XMLHttpRequest();
02
03 req.addEventListener( "progress" , updateProgress, false );
04 req.addEventListener( "load" , transferComplete, false );
05 req.addEventListener( "error" , transferFailed, false );
06 req.addEventListener( "abort" , transferCanceled, false );
07
08 req.open();
09
10 ...
11
12 // progress on transfers from the server to the client (downloads)
13 function updateProgress(evt) {
14 if (evt.lengthComputable) {
15 var percentComplete = evt.loaded / evt.total;
16 ...
17 } else {
18 // Unable to compute progress information since the total size is unknown
19 }
20 }
21
22 function transferComplete(evt) {
23 alert( "The transfer is complete." );
24 }
25
26 function transferFailed(evt) {
27 alert( "An error occurred while transferring the file." );
28 }
29
30 function transferCanceled(evt) {
31 alert( "The transfer has been canceled by the user." );
32 }

Lines 3-6 add event listeners for the various events that are sent while performing a data transfer using XMLHttpRequest . See nsIDOMProgressEvent and nsIXMLHttpRequestEventTarget for details on these events.

Note: You need to add the event listeners before calling open() on the request. Otherwise the progress events will not fire.

The progress event handler, specified by the updateProgress() function in this example, receives the total number of bytes to transfer as well as the number of bytes transferred so far in the event's total and loaded fields. However, if the lengthComputable field is false, the total length is not known and will be zero.

Progress events exist for both download and upload transfers. The download events are fired on the XMLHttpRequest object itself, as shown in the above sample. The upload events are fired on the XMLHttpRequest.upload object, as shown below:

1 var req = new XMLHttpRequest();
2
3 req.upload.addEventListener( "progress" , updateProgress, false );
分享到:
评论

相关推荐

    Ajax using XMLHttpRequest and Struts

    ajax和struts的结合应用

    Developing Hybrid Applications for the iPhone: Using HTML, CSS, and JavaScript to Build Dynamic Apps for the iPhone

    Using XMLHttpRequest to access or synchronize remote data and use web services Creating Google-based maps for your own app that work like those you see in the iPhone’s Maps application This book ...

    The WebSocket Protocol

    The WebSocket Protocol enables two-way communication between a client running untrusted code in a controlled environment to a remote host ...XMLHttpRequest or &lt;iframe&gt;s and long polling).

    realtime web apps

    The WebSocket protocol enables two-way communication between a user agent running untrusted code running in a controlled environment to a ... using XMLHttpRequest or &lt;iframe&gt;s and long polling). 16

    RFC 6455 - The WebSocket Protocol

    The WebSocket Protocol enables two-way communication between a client running untrusted code in a controlled environment to a remote host ... XMLHttpRequest or &lt;iframe&gt;s and long polling).

    外文翻译-XMLHttpRequest对象的使用 Using_the_XMLHttpRequest_Object

    Using the XMLHttpRequest Object Now that we’ve discussed the history of dynamic Web applications and introduced Ajax, it’s time to cover the heart of the matter: how to use the XMLHttpRequest ...

    javascript权威指南(第六版)

    18.1 Using XMLHttpRequest 494 18.2 HTTP by &lt;script&gt;: JSONP 513 18.3 Comet with Server-Sent Events 515 19. The jQuery Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ....

    ActiveWidgets 2.0.2

    ActiveWidgets controls generate html on the client-side and can communicate with the server asynchronously using XMLHTTPRequest object (AJAX-style). &lt;br/&gt;ActiveWidgets library includes powerful ...

    phdevsdir:WIP:尼日利亚哈科特港的Web开发人员目录应用程序。 使用React和Express构建

    PH开发人员目录 尼日利亚哈科特港面向Web开发人员的Directory应用程序。 使用React,Express和MongoDB构建 API文档 ... first_name (字符串)为... // using XMLHttpRequest // GET let request = new XMLHttpRequest

    Ajax for Web Application Developers(Ajax网站开发)

    An In-Depth Look at XMLHttpRequest Creating the Object Asynchronous Data Transfers The Ready State HTTP Status Codes and Headers Chapter 3. The Response XML JSON Chapter 4. Rendering ...

    AJAX+PHP+MYSQL聊天室

    Web form形式的网页 The chat lines are sent to the server using a XMLHttpRequest object. 使用XMLHttpRequest对象将chat lines发到服务器 The chat lines are received by a server side script ...

    Web_Communication_Tech_Spec:Web浏览器中的数据传输技术

    Web原生通信技术一览 (In progress) 请爱护浏览器! No Flash, No Hurt. ...fetch is an easier way to make web requests and handle responses than using an XMLHttpRequest 就是说fetch是用来取代XMLHTTPRequest

    sinon-server-backend

    // start using fake XMLHttpRequest server . start ( ) ; // restore XMLHttpRequest global function server . restore ( ) ; 设置可重复的响应: server . when ( 'GET' , '/test' ) . respond ( 200 , '...

    JavaScript跨域请求库XDomain.zip

    var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://xyz.example.com/secret/file.txt'); xhr.onreadystatechange = function(e) {  if(xhr.readyState === 4)  alert&#40;xhr.responseText&#41;...

    大名鼎鼎的IBM公司 Ajax 培训资料

    // Set some values on a form using an array called response document.getElementById("order").value = response[0]; document.getElementById("address").value = response[1]; 这里没有特别需要注意的...

    AJAX and PHP.pdf

    developing enterprise architectures using JavaScript, others prefer not to use it at all. When the hype is over, most will probably agree that the middle way is the wisest way to go for most ...

    Professional JavaScript for Web Developers, 3rd Edition

    using the &lt;canvas &gt; tag to create on-the-fly graphics JavaScript API changes in HTML5 how browsers handle JavaScript errors and error handling features of JavaScript used to read and manipulate XML ...

    Packtpub.Instant.Firebug.Starter.Jan.2013.pdf

    Track XmlHttpRequest and XmlHttpResponse as well as monitoring AJAX calls. Explore the value of properties and constants of any DOM object. Monitor, edit, and remove cookies from Firebug. ...

    JavaScript权威指南(第五版).chm

    Part IV is a reference for client-side JavaScript, covering legacy web browser APIs, the standard Level 2 DOM API, and emerging standards such as the XMLHttpRequest object and the &lt;canvas&gt; tag. ...

    javascript.the.definitive.guide.5th.2006(英文版)

    Part IV is a reference for client-side JavaScript, covering legacy web browser APIs, the standard Level 2 DOM API, and emerging standards such as the XMLHttpRequest object and the &lt;canvas&gt; tag. ...

Global site tag (gtag.js) - Google Analytics
4 req.upload.addEventListener( "load" , transferComplete, false );