为什么我必须调用NgZone.run来查看使用breezejs在Angular2中更新?

Jur*_*hen 8 promise typescript breeze ecmascript-6 angular

我正在尝试学习angular2并使用odata webapi后端创建了一个测试应用程序.在应用程序中,我有一个视图,它获取一个项目数组,我想在我的视图中显示这些.

为了从前端获取数据我正在使用breezejs库,因为它已经证明在过去节省了我很多时间,我喜欢将它与odata后端一起使用.

调用树和应用程序结构如下所示:

通过从视图中调用服务函数开始调用以开始获取项目(请注意,我将从每次调用返回es-6承诺):

this._scrumModuleService.fetchActiveSessions().then((sessions: ScrumSession[]) => {
    // Here i have to call zone.run else my view wont update.
    this._zone.run(() => {
        this.sessions = sessions;
    });
}).catch((error: any) => {
     debugger;
});
Run Code Online (Sandbox Code Playgroud)

然后从视图中它将转到服务,该服务又调用存储库:

public fetchActiveSessions(): Promise<ScrumSession[]> {
    return this._scrumSessionRepository.fetchActiveSessions();
}
Run Code Online (Sandbox Code Playgroud)

存储库获取功能:

public fetchActiveSessions(): Promise<ScrumSession[]> {
    return this._dataContext.fetch(new breeze.EntityQuery().from("ScrumSessions").expand(['creator', 'scrumRoom','productOwner', 'users']));
}
Run Code Online (Sandbox Code Playgroud)

然后最终存储库调用(通用)datacontext,它将使用breeze entitymanager执行查询:

public fetch(query: breeze.EntityQuery, isRetry: boolean = false): Promise<any> {

    return new Promise((resolve, reject) => {
            this.entityManager.executeQuery(query).then((result: breeze.QueryResult): void => {
            // Data has been fetched, resolve the results
            resolve(result.results);
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

现在你可以在视图中看到我必须使用NgZone的run函数,否则我的视图不会更新.我想知道为什么我必须这样做,因为我期待angular2自动为我看到这个.我已经挖掘了几个类似的问题,但还没找到答案.我还包括了另一个线程中建议的angular2-polyfills脚本,但是没有解决它.

我缺少什么或者我必须实现什么才能在不调用zone.run的情况下自动更新视图?

Jay*_*and 6

现在,Breeze和Angular2运行得很好.我们正在使用当前版本的Breeze和Angular Beta 8开发一个大型应用程序,没有任何问题.

目前唯一的轻微解决方法是微风还没有使用Angular2 http提供程序.但是,您可以在默认的"Q"提供程序中进行填充,以便它支持Angular2期望的ES6 Promises,其代码如下:

/**
 * Minimum necessary deferred object for breeze Q/ES6 Promise adapter
 * Makes ES6 promise look like Q. 
 */
export interface Deferred {
    promise: Promise<any>;
    resolve: (value?: {} | PromiseLike<{}>) => void;
    reject: (reason?: any) => void;
}

/**
 * Minimum for breeze breeze Q/ES6 Promise adapter
 */
export const Q = {
    defer(): Deferred {
        let resolve: (value?: {} | PromiseLike<{}>) => void;
        let reject: (reason?: any) => void;
        let promise = new Promise((_resolve, _reject) => {
            resolve = _resolve;
            reject = _reject;
        })
        return {
            promise: promise,
            resolve(value: any) { resolve(value); },
            reject(reason: any) { reject(reason); }
        }
    },

    resolve(value?: {} | PromiseLike<{}>) {
        let deferred: Deferred = Q['defer']();
        deferred.resolve(value);
        return deferred.promise;
    },


    reject(reason?: any) {
        let deferred: Deferred = Q['defer']();
        deferred.reject(reason);
        return deferred.promise;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以导入此文件

import { Q } from './q';

然后在你的应用程序顶部附近的某个地方

breeze.config.setQ(<breeze.promises.IPromiseService>Q);

此时,所有标准微风方法都与现在完全一样,Angular的变化检测也应该没有问题.


Gün*_*uer 3

Angular 运行在大多数异步 API 都已修补的区域中。当异步调用完成时,Angular 会运行更改检测。

不知何故,微风代码离开了 Angulars 区域并“破坏”了变更检测。这要么是因为您从 Angular 外部初始化 Breeze,要么是 Breeze 使用了一些未由 Angulars 区域修补的异步 API,因此回调是在 Angulars 区域外执行的。