我面临着Angular2路由器和异步管道的问题.
我试图渲染一个RxJs Observable,数据不会自动渲染.
这是根应用程序:
import {bootstrap} from 'angular2/platform/browser'; import {HTTP_PROVIDERS} from 'angular2/http'; import {ROUTER_PROVIDERS} from 'angular2/router'; import {AppComponent} from './app.component.ts'; bootstrap(AppComponent,[HTTP_PROVIDERS,ROUTER_PROVIDERS]);
这是根组件:
import {Component} from 'angular2/core'; import {RouteConfig,ROUTER_DIRECTIVES} from 'angular2/router'; import {FirstComponent} from './app.first-component.ts'; import {SecondComponent} from './app.second-component.ts'; import {AppService} from "./app.services.ts"; @Component({ selector: 'my-app',providers: [AppService,FirstComponent,SecondComponent],directives: [FirstComponent,SecondComponent,ROUTER_DIRECTIVES],template: `<h1>An Angular 2 App</h1> <a [routerLink]="['First']">first-default</a> <a [routerLink]="['Second']">second</a> <router-outlet></router-outlet>` }) @RouteConfig([ {path: '/',name: 'First',component: FirstComponent,useAsDefault: true},{path: '/second',name: 'Second',component: SecondComponent} ]) export class AppComponent { }
这是第一个组成部分:
import {Component} from "angular2/core"; import {AppService} from "./app.services.ts"; import "rxjs/Rx"; @Component({ selector: 'my-first',template: ` <div> <ul> <li *ngFor="#s of appService.someObservable$| async"> a string: {{ s }} </li> </ul> </div>` }) export class FirstComponent { constructor(private appService:AppService) { console.log('constructor','first'); } }
最后是服务(数据所在的位置):
import {Injectable} from "angular2/core"; import {Observable} from "rxjs/Rx"; @Injectable() export class AppService { constructor() { console.log('constructor','appService'); this.constructSomeObservable(); } someObservable$:Observable <string[]>; constructSomeObservable() { this.someObservable$= Observable.create(observer => { const eventSource = new EventSource('/interval-sse-observable'); eventSource.onmessage = x => observer.next(JSON.parse(x.data)); eventSource.onerror = x => observer.error(console.log('EventSource Failed')); return () => { eventSource.close(); }; }) .startWith([]) .scan((acc,value) => acc.concat(value)); } }
我在路由器或管道上出了什么问题?
请参阅github here上的示例项目.
编辑:这是组件的修改版本:
import {Component} from "angular2/core"; import {AppService} from "./app.services.ts"; import {Observable} from "rxjs/Rx"; @Component({ selector: 'my-first',template: ` <div> <ul> <li *ngFor="#s of someObservable$| async"> a string: {{ s }} </li> </ul> </div>` }) export class FirstComponent { someObservable$:Observable <string[]>; constructor(private appService:AppService) { console.log('constructor','first'); this.someObservable$= appService.someObservable$; } }
数据未在模板中更新.它与两个/单向绑定有关吗?
我认为angular zone不会修复eventSource.onmessage发出的事件,例如setTimeout,SetInterval或xhr请求
来自angular2-polyfills.js
/***/ function(module,exports,__webpack_require__) { /* WEBPACK VAR INJECTION */(function(global) {"use strict"; __webpack_require__(1); var event_target_1 = __webpack_require__(2); var define_property_1 = __webpack_require__(4); var register_element_1 = __webpack_require__(5); var property_descriptor_1 = __webpack_require__(6); var utils_1 = __webpack_require__(3); var set = 'set'; var clear = 'clear'; var blockingMethods = ['alert','prompt','confirm']; var _global = typeof window == 'undefined' ? global : window; patchTimer(_global,set,clear,'Timeout'); patchTimer(_global,'Interval'); patchTimer(_global,'Immediate'); patchTimer(_global,'request','cancelMacroTask','AnimationFrame'); patchTimer(_global,'mozRequest','mozCancel','webkitRequest','webkitCancel','AnimationFrame'); for (var i = 0; i < blockingMethods.length; i++) { var name = blockingMethods[i]; utils_1.patchMethod(_global,name,function (delegate,symbol,name) { return function (s,args) { return Zone.current.run(delegate,_global,args,name); }; }); } event_target_1.eventTargetPatch(_global); property_descriptor_1.propertyDescriptorPatch(_global); utils_1.patchClass('MutationObserver'); utils_1.patchClass('WebKitMutationObserver'); utils_1.patchClass('FileReader'); define_property_1.propertyPatch(); register_element_1.registerElementPatch(_global); // Treat XMLHTTPRequest as a macrotask. patchXHR(_global); var XHR_TASK = utils_1.zoneSymbol('xhrTask'); function patchXHR(window) { function findPendingTask(target) { var pendingTask = target[XHR_TASK]; return pendingTask; }
因此,您需要为eventsource.onmessage包装回调类似于:
app.services.ts
import {Injectable,NgZone} from "angular2/core"; // <=== 1) Don't forget to import the NgZone class import {Observable} from "rxjs/Rx"; @Injectable() export class AppService { constructor(private zone: NgZone) { // <== 2) Don't forget also to inject zone in constructor console.log('constructor','appService'); this.constructSomeObservable(); } someObservable$: Observable<string[]>; constructSomeObservable() { this.someObservable$= Observable.create(observer => { const eventSource = new EventSource('/interval-sse-observable'); eventSource.onmessage = x => this.zone.run(() => observer.next(JSON.parse(x.data))); // <=== 3) Wrap onmessage event eventSource.onerror = x => observer.error(console.log('EventSource Failed')); return () => { eventSource.close(); }; }) .startWith([]) .scan((acc,value) => acc.concat(value)); } }