将脚本加载承诺转换为Observable

时间:2018-02-14 07:16:07

标签: angular observable

我有这个脚本加载承诺,我需要转换为observable。我需要在ngOnDestroy上取消这个承诺,在googling之后我发现这是不可能的,因此我想把它转换成一个可观察的。

this.visualizePromise = new Promise((resolve, reject) => {
    script.setAttribute('src', `${process.env.JASPER_SERVER}/client/visualize.js`);
    script.onload = () => {
        console.log('script loaded')
        window['visualize']({
            auth: {
                name: process.env.JASPER_NAME,
                password: process.env.JASPER_PASSWORD,
                organization: process.env.JASPER_ORGANIZATION
            }
        }, resolve, reject);
    };
    script.onerror = () => {
        this.errMsg = true;
        this.error = 'Failed to load visualize';
        this.showLoader = false;
    };
    document
        .body
        .appendChild(script);
});

this
    .visualizePromise
    .then(visualize => {
        if (typeof visualize.report === 'function') {
            return visualize;
        }
        throw 'Failed to load visualize';
    })
    .then(visualize => {
        this.visualize = visualize;
        this.showLoader = false;
        // do stuff here
    })
    .catch(() => {
        this.errMsg = true;
        this.error = 'Failed to load visualize';
        this.showLoader = false;
    });

我想把它改成这样的东西,

import { Observable } from "rxjs/Observable"

// create observable
const simpleObservable = new Observable((observer) => {

    // observable execution
    observer.next("bla bla bla")
    observer.complete()
})

// subscribe to the observable
simpleObservable.subscribe()

// dispose the observable
simpleObservable.unsubscribe()

2 个答案:

答案 0 :(得分:1)

在评论中作出澄清后,您可以执行以下操作。我保留了你的所有逻辑,包括script.onerror拒绝(或解决)承诺的(可疑的)决定。因此,如果脚本无法加载,则此observable将永远不会完成。

const visualize$ = Observable.create(observer => {
  const resolve = val => {
    observer.next(val);
    observer.complete();
  };

  script.setAttribute('src', `${process.env.JASPER_SERVER}/client/visualize.js`);

  script.onload = () => window['visualize']({
    auth: {
      name: process.env.JASPER_NAME,
      password: process.env.JASPER_PASSWORD,
      organization: process.env.JASPER_ORGANIZATION
    }
  }, resolve, observer.error);

  script.onerror = () => {
    this.errMsg = true;
    this.error = 'Failed to load visualize';
    this.showLoader = false;
  };

  document.body.appendChild(script);
});

旁注,你提到了

// dispose the observable
simpleObservable.unsubscribe()

这将永远不会起作用,因为取消订阅发生在订阅上,而不是发生在可观察的上。

答案 1 :(得分:0)

我做了一个实例,请查看convert-script-load-promise-to-observable。请记住,如果您想将auth标头添加到某个请求中,则应该在Interceptor中执行此操作。

<强> your.component.ts

ngOnInit() {
      let script, process;
      this.mySubcription = this.service.fromPromiseToObservable(script, process)
          .do(visualize => {
              this.visualize = visualize;
              this.showLoader = false;
              // do stuff here
          }).subscribe(visualize => {
              if (typeof visualize.report === 'function') {
                  return visualize;
              }
            return Observable.throw('Failed to load visualize');
    }, () => {
        this.service.errMsg = true;
        this.service.error = 'Failed to load visualize';
        this.service.showLoader = false;
    });
  }

  ngOnDestroy() {
      this.mySubcription.unsubscribe();
  }

<强> your.service.ts

fromPromiseToObservable(script, process): Observable<any> {
      this.visualizePromise = new Promise((resolve, reject) => {
      script.setAttribute('src', `${process.env.JASPER_SERVER}/client/visualize.js`);
      script.onload = () => {
          console.log('script loaded')
          window['visualize']({
              auth: {
                  name: process.env.JASPER_NAME,
                  password: process.env.JASPER_PASSWORD,
                  organization: process.env.JASPER_ORGANIZATION
              }
          }, resolve, reject);
      };
      script.onerror = () => {
          this.errMsg = true;
          this.error = 'Failed to load visualize';
          this.showLoader = false;
      };
      document
          .body
          .appendChild(script);
    });

    return Observable.fromPromise(this.visualizePromise);
  }