我正在尝试学习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;
});
然后从视图中它将转到服务,该服务又调用存储库:
public fetchActiveSessions(): Promise<ScrumSession[]> {
return this._scrumSessionRepository.fetchActiveSessions();
}
存储库获取功能:
public fetchActiveSessions(): Promise<ScrumSession[]> {
return this._dataContext.fetch(new breeze.EntityQuery().from("ScrumSessions").expand(['creator', 'scrumRoom','productOwner', 'users']));
}
然后最终存储库调用(通用)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);
});
});
}
现在你可以在视图中看到我必须使用NgZone的run函数,否则我的视图不会更新。我想知道为什么我必须这样做,因为我期待angular2自动为我看到这个。 我已经挖掘了几个类似的问题,但还没找到答案。我还包括了另一个线程中建议的angular2-polyfills脚本,但是没有解决它。
我缺少什么或者我必须实现什么才能让我的视图在不调用zone.run的情况下自动更新?
答案 0 :(得分:6)
现在,Breeze和Angular2一起运行得很好。我们正在使用当前版本的Breeze和Angular Beta 8开发大型应用程序,没有任何问题。
目前唯一的轻微解决方法是breeze尚未使用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;
}
}
然后您可以导入此文件
import { Q } from './q';
然后靠近应用顶部的某个地方
breeze.config.setQ(<breeze.promises.IPromiseService>Q);
此时,所有标准微风方法都与现在完全一样,Angular的变化检测也应该没有问题。
答案 1 :(得分:3)
Angular在修补了大多数异步API的区域中运行。完成异步调用时,Angular运行会更改检测。
以某种方式,微风代码留下了Angulars区域和&#34;休息&#34;改变检测。这可能是因为您从Angular外部初始化breeze或者breeze使用了一些未被Angulars区域修补的异步API,因此回调在Angulars区域外执行。
答案 2 :(得分:3)
是的,“问题”是你使用的是区域不知道的某种承诺库(例如Q)。幸运的是,promise库可以在Breeze中插入,我们编写了一个效果很好的ES6 promise插件。
我们尚未发布它(参见上面的Jay的回答),我们还没有编写Angular 2 http
插件。
两者都很容易,但我们一直非常忙碌。看起来好像是时候了。