链接可观察量

时间:2018-03-29 17:34:06

标签: fabricjs angular5 rxjs5

我知道这已被问了好几次,但是我找不到一个在Angular 5中使用rxjs5的解决方案。

TL; DR; 如何使这4个可观察对象按顺序同步运行:

    const getImage$ = this.fileService.getImage(this.shape.imageFile.id);
    const getUrl$ = Observable.create((blob: Blob) => {
        return URL.createObjectURL(blob);
    });
    const fromURL$ = Observable.bindCallback(fabric.Image.fromURL);
    const addImage$ = Observable.create((img: any) => {
        this.shapeElement = img;
        this.shapeGroup = new fabric.Group([this.shapeElement], {
            lockScalingFlip: true,
            centeredRotation: true,
            angle: this.shape.rotation
        });
        this.fabric.add(this.shapeGroup);
    } );

然后返回Observable,这样我就可以在订阅者中做更多的事情。

更长的版本......

我有一个文件服务请求图像并返回blob的observable:

getImage(id) => Observable<Blob>

然后我需要获取此blob的网址:

URL.createObjectURL(blob)

我需要将它加载到一个FabricJS画布,它有一个带回调的函数。我从中创造并观察到:

fromURL = Observable.bindCallback(fabric.Image.fromURL)

最后,在返回observable之前,我需要摆弄Fabric创建的图像对象 - 订阅有更多内容来更新ui。

this.shapeGroup = new fabric.Group([this.shapeElement], {
   lockScalingFlip: true,
   centeredRotation: true,
   angle: this.shape.rotation,
   tag: Date.now()
  });
this.shapeGroup.shapeView = this;
this.shapeGroup.setShadow(this.getShadow());
this.canvas.fabric.add(this.shapeGroup);

这是我迷路的地方。我试图理解mergeMap和map和pipe以及其他一些东西,但我不能让它工作。

以前有人在这做过这样的事吗?这似乎过于复杂。

我有一个开始:

draw(): Observable<ImageView> {  

  const fromURLOb = Observable.bindCallback(fabric.Image.fromURL);

  return Observable.create(o => {
    if (this.shape.imageFile) {
      console.log('started loading');               
      o.next(this.fileService.getImage(this.shape.imageFile.id));
    }
    o.complete();
  })
 ...

哪个有效,但之后我失去了。

解决方案<!/强>

感谢@Ingo,这是我的工作版本。

    draw(): Observable<ImageView> {
      return this.fileService.getImage(this.shape.imageFile.id)
        .map(blob => URL.createObjectURL(blob))
        .switchMap<string, any>(url => {
            return Observable.bindCallback(fabric.Image.fromURL).call(this, url);
        })
        .do<ImageView>(image => {
            this.handleImage(image);
            return this;
        });
}

1 个答案:

答案 0 :(得分:2)

这里有一些事情发生:

  1. URL.createObjectURL实际上只是一个同步函数,它不会返回一个observable。因此,您只需使用map将结果从getImage映射到网址。
  2. fromUrl调用确实使用了回调,因此您可以像使用bindCallback一样使用但是,bindCallback不返回observable(如您所示),而是返回一个返回observable的函数。所以你需要用你得到的URL调用该函数;你可以在这里使用switchMap或其中一个变体;因为你只处理“发射一次并完成”可观测量,所以这些变体之间的差异并不重要。
  3. 您正在进行的最终处理实际上只是一个不会影响您想要返回的值的副作用,因此您只需使用do运算符来执行副作用。
  4. 您对Observable.create的使用表明存在一些误解。传递给Observable.create 的函数始终接收一个观察者作为参数,而不是一些值。我认为你在这里混淆了功能和可观察性。
  5. 因此,您可以这样做:

    private handleImage(img: any) {
        this.shapeElement = img;
        this.shapeGroup = new fabric.Group([this.shapeElement], {
            lockScalingFlip: true,
            centeredRotation: true,
            angle: this.shape.rotation
        });
    
        this.fabric.add(this.shapeGroup);
    }
    
    draw() {
      return this.fileService.getImage(this.shape.imageFile.id)
        .map(blob => URL.createObjectURL(blob))
        .switchMap(url => Observable.bindCallback(fabric.Image.fromURL)(url))
        .do(image => this.handleImage(image));
    }