Typescript Angular - Observable:如何更改其值?

Posted

技术标签:

【中文标题】Typescript Angular - Observable:如何更改其值?【英文标题】:Typescript Angular - Observable: how to change its value? 【发布时间】:2017-07-19 15:29:28 【问题描述】:

也许我错过了什么。我找不到 Observable 及其语法的简单教程。我正在使用 Angular,我需要从服务中调用一个函数(在组件中定义)。我读了这个solution。但是我不知道如何更改服务中创建的 Observable 中的值(也许创建不是最好的方法)。

我有一个类似解决方案的组件:

@Component(
  selector: 'my-component',
  ...
)
export class MyComponent 
   constructor(myService:MyService) 
   myService.condition.subscribe(value => doSomething(value));


doSomething(value) 
  if (value) // do stuff
  else // other stuff

这是我的服务:

import  Injectable  from '@angular/core';
import  Observable from 'rxjs/Observable';

@Injectable()

export class MyService 
    private condition: Observable<boolean>;
    constructor()  
       this.condition= new Observable(ob => ob.next(false); )
       // maybe ob.next is not the best solution to assign the value?
    

    change() // how can i change the value of condition to 'true', to call
              // the doSomething function in the component?? 
    


【问题讨论】:

我无法准确提取您想要执行的操作。您能否为您的问题提供更多背景信息?你(认为)为什么要从服务中调用组件函数?一个 Observable 有点像一个 Promise:通常用在一个组件中,当一些异步操作完成时,你要求服务返回一个 Observable,并对其采取行动,所有这些都来自一个组件(或另一个服务)。 您链接的另一个问题与使用服务作为两个组件之间的中介有关。这是你想做的吗? this.condition = Observable.of(false) 适合你吗? 示例:我有一个组件“A”显示日志状态(登录/退出),另一个组件“B”用于管理登录(用户名/密码表单和登录按钮)。服务“S”是我存储一些会话信息的地方,比如日志状态。因此,当我使用“B”按钮登录时,我将此信息存储在变量/可观察的“条件”中。 'A' 组件订阅了那个 observable,所以 'A' 组件“知道”日志状态何时改变并且可以改变刷新一些 html/css 不,Observable.of 不起作用 【参考方案1】:

从my other answer 上的 cmets(保留,因为它可能对某人有帮助),您似乎想利用某物的力量随着时间的推移发出值。

正如 DOMZE 建议的那样,使用主题,但这里有一个(简单的)示例,显示如何你可以做到这一点。虽然显然有some pitfalls to avoid in using Subject directly,但我会留给你。

import  Component, NgModule  from '@angular/core'
import  BrowserModule  from '@angular/platform-browser'
import  Observable, Subject  from 'rxjs/Rx';

@Component(
  selector: 'my-app',
  template: `
    <div>
      <h2>Open the console.</h2>
    </div>
  `,
)
export class App 

  constructor() 

  let subject = new Subject();

  // Subscribe in Component
  subject.subscribe(next => 
    console.log(next);
  );

  setInterval(() => 
    // Make your auth call and export this from Service
    subject.next(new Date())
  , 1000)


@NgModule(
  imports: [ BrowserModule ],
  declarations: [ App ],
  bootstrap: [ App ]
)
export class AppModule 

Plunker

以我的拙见,对于这种情况,我不明白为什么一个简单的 Service/Observable 是不够的,但这不关我的事。

延伸阅读:Angular 2 - Behavior Subject vs Observable?

【讨论】:

谢谢!可能我的问题的解释不太好(我不是英语),所以谢谢你的耐心。我尝试了 Subject ,它似乎非常适合我的目的(和 BehaviorSubject )。 @Johannes 这对我来说也是一个有趣的问题,所以不客气! (而且你的英语很好,我也来自其他语言背景;))【参考方案2】:

如果您想更新值,我想解释如何使用 Observables,但我不会使用您的示例。我将展示几行用 ES5 编写的代码并附上解释。

var updateObservable; // declare here in order to have access to future function

var observable = rx.Observable.create(function (observer) 
  observer.next(1);
  observer.next(2);
  observer.next(3);

  // attach a function to the variable which was created in the outer scope
  // by doing this, you now have your 'updateObservable' as a function and the reference to it as well
  // You will be able to call this function when want to update the value
  updateObservable = function (newValue) 
    observer.next(newValue);
    observer.complete();
  ;
);

// Suppose you want to update on click. Here actually can be whatever (event) you want
vm.click = function () 
  // you can call this function because you have a reference to it
  // and pass a new value to your observable
  updateObservable(4);
;

// your subscription to changes
observable.subscribe(function(data) 
  // after 'click' event will be performed, subscribe will be fired
  // and the '4' value will be printed
  console.log(data);
);

这里的主要思想是,如果您想更新 Observable 的值,您必须在“create”函数中执行此操作。如果你在这个“创建”函数中声明一个函数,这将是可能的。

【讨论】:

它对我有用,在 Angular 8 中看起来像这样:` import Observable from 'rxjs'; // 在 de Service 声明中直到 constructor() public schoolObservable = new Observable(observer => observer.next(this.schoolID); this.updateObservable = (newValue) => observer.next(newValue);observer.complete (); ; ); // 然后在我的函数中,当我有值时调用该方法 if (selectOp[0]) this.schoolID = Number(selectOp[0].id); this.updateObservable(this.schoolID); // 在另一个组件中 `【参考方案3】:

管理登录状态

对于这个实现,您只需要一个服务。在其中,您将发出后端请求以查看用户是否有会话,然后您可以将其保存在服务的类变量中。然后,如果设置了该变量,则返回该变量,或者直接返回 REST 调用的结果。

例如:

export class AuthenticationService 

 private loggedIn: boolean = null;

 constructor(private http: Http)  

 getUserSession(credentials): Observable<boolean> 

  if (this.loggedIn !== null) 

    return Observable.of(this.loggedIn);

   else 

    return this.http.get('/authenticate?' + credentials)
      .map((session: Response) => session.json())
      .catch(e => 
        // If a server-side login gate returns an HTML page...
        return Observable.of(false);
      );

  

然后在组件中,像往常一样订阅 Observable 并按需操作。

Observable.share()Observable.replay() 还有其他方法可以实现这一目标

可观察语法

要回答有关 Angular2 中 Rx Observable 语法的部分问题(如果有人谷歌它),通用形式是:

在服务中:

return this.http.get("/people", null)
  .map(res.json())
  .catch(console.error("Error in service")

在一个组件中,例如:

this.someService.getPeople()
  .subscribe(
    people => this.people,
    error => console.warn('Problem getting people: ' + error),
    () => this.doneHandler();
  );

正式地:

interface Observer<T> 
  onNext(value: T) : void
  onError(error: Error) : void
  onCompleted() : void

当接收到“下一个”值时调用第一个函数。对于 REST 调用(最常见的情况),它包含整个结果。

第二个函数是错误处理程序(在服务中调用 Observable.trow() 的情况下)。

当结果集有时调用最后一个,并且不带任何参数。这是您可以调用 doSomething() 函数的地方。

【讨论】:

谢谢,我正在尝试这个方法。但总的来说,我想了解一种“告诉”组件 X 在服务中更改了变量值的方法;所以,在一个组件中,我想订阅那个变量。 @Johannes 我明白你的意思,所以这就是你为什么要使用Observable.next(),所以你可以像使用 ES6 *generator 一样使用它?或者保持双向数据绑定的精神,只是从Service到Component,而不是Component到View。想到了一些不太习惯 ng2 的想法,但这是一个有趣的问题,所以我会自己检查一下,如果我发现了什么,我会发布另一个答案。【参考方案4】:

我建议您将您的条件更改为主题。主体既是观察者又是可观察者。然后,您将能够发出一个值。

见https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/subjects.md

【讨论】:

以上是关于Typescript Angular - Observable:如何更改其值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular Universal 中检测屏幕分辨率?

带有 TypeScript 的 Angular 2 [关闭]

没有 TypeScript 的 Angular 8 依赖注入?

Angular 指令依赖注入 - TypeScript

typescript Angular 4基本动画#angular #js

Angular (TypeScript) 模型