首页 文章

Typescript Angular2:订阅Observable会导致“无法识别的拆卸1”错误

提问于
浏览
3

我在Angular2.rc.4 Typescript应用程序中使用Observable时遇到问题 . 我这里有一个吸烟者:https://embed.plnkr.co/UjcdCmN6hSkdKt27ezyI/

本质上,该应用程序有一个具有以下代码的服务:

private messageSender : Observable<string>;

constructor() {
    this.messageSender = Observable.create(observer => this.clients.push(observer));
 }

public listenForMessages() : any {
    console.log("Listen Requested...")
    return this.messageSender;
}

我想从一个组件中听取它:

ngOnInit() {
    this.chatter.listenForMessages().subscribe(msg => console.log(msg));
}

这给了我以下错误:

EXCEPTION: Error: Unrecognized teardown 1 added to Subscription.
Error: Unrecognized teardown 1 added to Subscription.
    at Subscriber.Subscription.add (Subscription.ts:151)
    at Observable.subscribe (Observable.ts:93)
    at LoginPage.ngOnInit (login.ts:15)
    at DebugAppView._View_LoginPage_Host0.detectChangesInternal (LoginPage.template.js:29)
    at DebugAppView.AppView.detectChanges (view.ts:261)
    at DebugAppView.detectChanges (view.ts:377)
    at DebugAppView.AppView.detectContentChildrenChanges (view.ts:280)
    at DebugAppView.AppView.detectChangesInternal (view.ts:272)
    at DebugAppView.AppView.detectChanges (view.ts:261)
    at DebugAppView.detectChanges (view.ts:377)
BrowserDomAdapter.logError @ browser_adapter.ts:82

如果使用transpile tsc或允许在浏览器中发生这种情况,并且我以ES6或ES5为目标,则会发生同样的错误 .

我已经看了几个小时,我发现在任何其他网站上都没有引用它 . 该错误消息来自RxJS,它检查传入.subscribe()方法的内容,检查其类型是“对象”还是“函数”,如果不是,则会发出此错误 . 我已经通过lambdas,如在plunker或预定义的函数,他们导致相同的问题 .

有任何想法吗?如果我在组件中创建Observable,那么没有问题 . 如果我在服务中订阅,那么我会得到同样的错误......很困惑 .

3 回答

  • 1

    您的问题是 Array#push 返回一个数字(这是 Array 的新长度),当您执行 Observable.create(observer => this.clients.push(observer)) 时,它正尝试将其用作新的 TeardownLogic .

    我建议你 do not 使用观察者阵列模式,你只是诚实地重新发明轮子,你不太可能正确地做到这一点(*注意:它没有看到它突然出现在ng2教程中,它只是一个糟糕的,糟糕的模式) .

    如果你需要多播行为,你应该使用 Subject 代替:

    private messageSender : Subject<string>;
    
    constructor() {
        this.messageSender = new Subject<string>();
     }
    
    public listenForMessages() : any {
        console.log("Listen Requested...")
        return this.messageSender.asObservable();
    }
    

    一个更好的解决方案是完全取消中间 Subject 并直接订阅消息源,但是在不知道更多关于你的应用程序的情况下,我实际上无法说明你如何解决这个问题 .

  • 0

    对于其他有类似错误消息的人 . 你可能没有传递 Object.create 一个回调函数返回 TeardownLogic . 哪里:

    export type TeardownLogic = AnonymousSubscription | Function | void;
    

    在哪里

    export interface AnonymousSubscription {
      unsubscribe(): void;
    }
    

    例如,我正在返回 boolean

    this.showSomething = Observable.create((observer: Observer<boolean>) => this.code === "00108");
    

    什么时候我应该回来 AnonymousSubscription

    this.showSomething = Observable.create((observer: Observer<boolean>) => {
        observer.next(this.code === "00108");
    });
    
  • 3

    刚刚完成@Tom回答,我遇到了同样的问题,因为我没有处理Observer .

    Wrong implementation:

    @Injectable()
    export class QuizEditorGuard implements CanDeactivate<QuizEditorPage> {
    
      constructor(private app: ApplicationService) { }
    
      canDeactivate(
        quizEditor: QuizEditorPage,
        currentRoute: ActivatedRouteSnapshot,
        currentState: RouterStateSnapshot,
        nextState: RouterStateSnapshot
      ): Observable<boolean> | Promise<boolean> | boolean {
        return Observable.create((observer: Observer<boolean>) => {
          if (quizEditor && quizEditor.hasUnsavedChanges) {
            observer.next(true);
            observer.complete();
          }
          else
            return false; //here is the problem
        });
      }
    }
    

    Correct Implementation:

    @Injectable()
    export class QuizEditorGuard implements CanDeactivate<QuizEditorPage> {
    
      constructor(private app: ApplicationService) { }
    
      canDeactivate(
        quizEditor: QuizEditorPage,
        currentRoute: ActivatedRouteSnapshot,
        currentState: RouterStateSnapshot,
        nextState: RouterStateSnapshot
      ): Observable<boolean> | Promise<boolean> | boolean {
        return Observable.create((observer: Observer<boolean>) => {
          if (quizEditor && quizEditor.hasUnsavedChanges) {
            observer.next(true);
            observer.complete();
          }
          else {
            observer.next(false); //always implement next to warn observer
            observer.complete();
          }
        });
      }
    }
    

    回到@Steven问题,他的错误也是出于同样的原因:他创建了一个观察者而没有告诉他的对象在客户端插入后要做什么 .

    Observable.create(observer => 
        this.clients.push(observer));
        observer.next("some string");
        observer.complete();
     }
    

相关问题