Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get access to XHR in $http with Angular?

Currently I am try to implement the upload function with Angular. At first I used XmlHttpRequest but later I changed it to $http. So I found that I could't get access to XmlHttpRequest to create a progress bar with $http. Below is my code. Any suggestions about create a progress bar when uploading images? Thanks.

    $http({
          method: 'POST',
          url: upload_url,
          data: fd, 
          headers: {'Content-Type': undefined}, 
          transformRequest: angular.identity
          })
like image 466
aldrich Avatar asked May 27 '13 08:05

aldrich


People also ask

What is XHR fetch?

The Fetch API allows you to make network requests similar to XMLHttpRequest (XHR). The main difference is that the Fetch API uses Promises, which enables a simpler and cleaner API, avoiding callback hell and having to remember the complex API of XMLHttpRequest.

Can I use fetch in angular?

Angular offers HttpClient to work on API and handle data easily. In this approach HttpClient along with subscribe() method will be used for fetching data. The following steps are to be followed to reach the goal of problem.


1 Answers

Here the way of getting xhr object:

http://boylesoftware.com/blog/angular-tip-using-the-xmlhttprequest-object/

Copy/Paste:

Normally, an AngularJS application uses the $http service to make calls to back-end services. Sometimes, however, we would like to have access to the underlying XMLHttpRequest object. I can come up with a few use-cases, but the most prominent one is probably being able to track progress of a long request, such as a file upload. To do that, we need to register an event listener on the XMLHttpRequest object for the event that is “in progress.” Surprisingly enough, Angular’s $http service does not in any way expose the underlying XMLHttpRequest object. So, we have to get creative. Here is one way to do it…

The $http service’s config object allows us to add headers to the HTTP request via its “headers” property. That means that at some point $http has to set those headers on the XMLHttpRequest object it uses. The way to do that is to use XMLHttpRequest’s setRequestHeader method. So the idea is to override the setRequestHeader method on the XMLHttpRequest’s prototype and use a special header name to introduce a hook. Let’s begin with that and create a simple Angular module that performs the method substitution in its configuration phase:

angular.module("bsworksXHR", []).config([
    function() {
        XMLHttpRequest.prototype.setRequestHeader = (function(sup) {
            return function(header, value) {
                if ((header === "__XHR__") && angular.isFunction(value))
                    value(this);
                else
                    sup.apply(this, arguments);
            };
        })(XMLHttpRequest.prototype.setRequestHeader);
    }
]);

Now, when we make an $http service call, we can add a header called “XHR” with a function value that will receive the XMLHttpRequest object as its only argument. For example, somewhere else in the application:

$http({
    …
    headers: {
        …
        __XHR__: function() {
            return function(xhr) {
                xhr.upload.addEventListener("progress", function(event) {
                    console.log("uploaded " + ((event.loaded/event.total) * 100) + "%");
                });
            };
        },
        …
    },
    …
}).success(…);

Hopefully, future versions of AngularJS will include some official way to access the low-level XMLHttpRequest object, even if limited, such as being able to register event listeners or translating the XMLHttpRequest events into Angular events. Until then, I am using the approach above in my apps.

like image 196
WebBrother Avatar answered Oct 20 '22 03:10

WebBrother