2

In angular2 needed to create a global intercept http request, to capture including page requests via templateUrl in @Component decorator.

Then I implemented as follows:

(function (open) {

    XMLHttpRequest.prototype.open = function (method, url, async, user, pass) {

        this.addEventListener("readystatechange", function (data) {
            if (data.target.readyState === 4) {
                console.log(data);
                console.log(data.target.responseURL);
            }
        }, false);
        open.call(this, method, url, async, user, pass);
    };

})(XMLHttpRequest.prototype.open);

But this implementation works but ends up causing a recurring error on the console, when making a request to the server via object Http, despite the implementation seem to continue functioning properly.

The error is the following:

core.umd.js:3370 EXCEPTION: More tasks executed then were scheduled.
core.umd.js:3375 ORIGINAL STACKTRACE:
core.umd.js:3376 Error: More tasks executed then were scheduled.
    at ZoneDelegate._updateTaskCount (zone.js:269)
    at ZoneDelegate.invokeTask (zone.js:240)
    at Zone.runTask (zone.js:136)
    at ZoneTask.invoke (zone.js:304)
    at XMLHttpRequest.<anonymous> (zone.js:1266)
    at ZoneDelegate.invokeTask (zone.js:236)
    at Object.onInvokeTask (core.umd.js:6149)
    at ZoneDelegate.invokeTask (zone.js:235)
    at Zone.runTask (zone.js:136)
    at XMLHttpRequest.ZoneTask.invoke (zone.js:304)

And before the error appears the following warnnig:

Synchronous XMLHttpRequest on the main thread is deprecated
because of its detrimental effects to the end user's experience.
For more help, check https://xhr.spec.whatwg.org/.

I saw the zone.js abstracts and manages asynchronous requests and I believe that the line open.call(this, method, url, async, user, pass); is the cause of the problem. So I think I should make this code block also managed zone.js, since it looks like I'm making the request out of it with this interceptor. That's right? How would I do that?

Environment:

  • Angular: 2.0.2;
  • zone.js: 0.6.25
Fernando Leal
  • 9,875
  • 4
  • 24
  • 46

1 Answers1

1

Possible alternative solution:

I changed the way I intercepted XMLHttpRequest requests. Because the way it was being done ended up creating a new XMLHttpRequest request completely outside the context of zone.js, which possibly resulted in the problem.

The alternative I tried and I'm using is to intercept and continue the same request without losing the original context. Here's the alternative to the question code:

(function (_that) {
    // Stores the current instance
    var proxied = XMLHttpRequest.prototype.open;
    // Override the current instance
    XMLHttpRequest.prototype.open = function () {
        this.addEventListener("readystatechange", function (data) {
            if (data.target.readyState === 4) {
                console.log(data);
                console.log(data.target.responseURL);
            }
        }, false);

        // Continuous request for current instance
        return proxied.apply(this, [].slice.call(arguments));
    };
})(this);

Solution based on this answer: https://stackoverflow.com/a/7778218/2290538

Note: This is working for my specific case, I have no guarantee that this is a comprehensive solution. Please let me know of possible alternatives or improvements to the solution.

Community
  • 1
  • 1
Fernando Leal
  • 9,875
  • 4
  • 24
  • 46