错误:已安排执行更多任务。在Angular 2中使用XMLHttpRequest.open

时间:2016-10-20 11:27:08

标签: angular xmlhttprequest angular2-http zone

在angular2中创建全局拦截http请求,通过templateUrl装饰器中的@Component捕获包含页面请求。

然后我按如下方式实施:

(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);

但是这个实现工作但最终在通过对象Http向服务器发出请求时导致控制台上出现重复错误,尽管实现似乎仍能正常运行。

错误如下:

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)

在出现错误之前,请注意以下警告:

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/.

我看到zone.js抽象并管理异步请求,我认为行open.call(this, method, url, async, user, pass);是导致问题的原因。所以我认为我应该使这个代码块也管理zone.js,因为它看起来像我用这个拦截器发出请求。那对吗?我该怎么做?

环境:

  • Angular:2.0.2;
  • zone.js:0.6.25

1 个答案:

答案 0 :(得分:1)

可能的替代解决方案:

我改变了拦截XMLHttpRequest请求的方式。 因为它的完成方式最终会在XMLHttpRequest的上下文之外创建一个新的zone.js请求,这可能会导致问题。

我尝试过的另一种选择是拦截并继续相同的请求而不会丢失原始上下文。这是问题代码的替代方案:

(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);

基于此答案的解决方案:https://stackoverflow.com/a/7778218/2290538

  

注意:这适用于我的具体情况,我无法保证这是一个全面的解决方案。请告诉我解决方案的可能替代方案或改进。