在Angular2 +中定义自定义Observable

时间:2017-07-17 21:47:21

标签: angular rxjs observable

我有一个简单的css animation库,允许通过调用loadService.animate(boolean);来显示动画,但遗憾的是它不再起作用,因为我在我的服务中错误地使用了EventEmitter这样:

@Injectable()
export class LoadService {
    @Output() animating: EventEmitter<any> = new EventEmitter();

    constructor() {}

    // User calls animate, we emit an event with the new boolean value
    public animate(val: boolean) {
        this.animating.emit(val);
    }

    getValue(): any {
        return this.animating;
    }
}

在我的组件中订阅它:

// Animation shown when animate == true
animate: boolean;

ngOnInit(): void {
    this.loadService.getValue().subscribe((status: boolean) => {
        // Events caught, we change the boolean to display the animation
        this.animate = status;
    });
    this.handleShape();
}

但是我的订阅从未捕获任何内容,所以我想我想创建自定义Observable ,以便在用户调用animate时捕获并因此更改值我的布尔值。

如何在Angular2 +中定义自定义observable?我如何在这种情况下实现它?

2 个答案:

答案 0 :(得分:2)

LoadService

在我们的服务中,我们创建了一个BehaviorSubject,其默认值为false

private _animate = BehaviorSubject(false);
get animate(): Observable<any>{
    return this._animate.asObservable();
}

另外,在LoadService中,要更新我们的observable值:

toggleAnimation(value: boolean){
   oldValue = this._animate.getValue();
   this._animate.next(!oldValue);
}

组件

现在在我们的组件中,您可以像这样订阅它:

constructor(private service: LoadService) {
    this.service.animate.subscribe(state => {
        // do stuff
        console.log(state);
    })
};

答案 1 :(得分:0)

Angular团队不鼓励在服务中使用eventemitter,因为它被用作围绕主题的抽象。您可以通过使用新的关键字来创建具有自定义逻辑的observable,并提供发射的逻辑,或者您可以使用Subject(一个可观察的和观察者),将其视为观察者模式的最相似的实现

function importData() {
  var fSource = DriveApp.getFolderById("0ByXeCX01JfKJN1dTNk1SRlQyb1k"); // reports_folder_id = id of folder where csv reports are saved
  var fi = fSource.getFilesByName('201707160600070685.csv'); // latest report file
  var ss = SpreadsheetApp.openById("1T2JU4KwpJsnlJk0LOEZoHr9uqnNrVYwBWI1NxOwL4PU"); // data_sheet_id = id of spreadsheet that holds the data to be updated with new report data


      if ( fi.hasNext() ) { // proceed if "report.csv" file exists in the reports folder
        var file = fi.next();
        var csv = file.getBlob().getDataAsString();
        var csvData = CSVToArray(csv); // see below for CSVToArray function
        var newsheet = ss.insertSheet("NEWDATA"); // create a 'NEWDATA' sheet to store imported data
        // loop through csv data array and insert (append) as rows into 'NEWDATA' sheet
        for ( var i=0, lenCsv=csvData.length; i<lenCsv; i++ ) {
          newsheet.getRange(i+1, 1, 1, csvData[i].length).setValues(new Array(csvData[i]));
        }
        /*
        ** report data is now in 'NEWDATA' sheet in the spreadsheet - process it as needed,
        ** then delete 'NEWDATA' sheet using ss.deleteSheet(newsheet)
        */
        // rename the report.csv file so it is not processed on next scheduled run
        file.setName("report-"+(new Date().toString())+".csv");
      }
    };

将主题视为事件发射器和侦听器之间的代理,无论何时调用主题上的下一个函数,发出的值都将被推送到observable的所有订阅者。

loadServiceSubject : Subject<any> = new Subject();
loadService$ : Observable<any> = loadServiceSubject.asObservable();
// other code

“事件”发射器只需要调用主题本身的下一个,错误或完整函数。

// in client code
// suppose the service is injected in the constructor
this.animationService.loadService$.subscribe( this.doStuffOnNextCallback );