【问题标题】:How to return Observable from Promise如何从 Promise 返回 Observable
【发布时间】:2018-04-25 12:00:11
【问题描述】:

我需要从 Promise 中返回 Observable,但是我在尝试学习 Angular 时被语法所困扰。所以事情是这样的:

我有一个以下函数 getCountries(这是由另一个实用程序订阅的),我需要调用以检索国家/地区列表。'lang' 尚未定义。我添加它只是为了完成我的 api 的 url。

getCountries(): Observable<Country[]> {
    if (this.countries) {
       return Observable.of(this.countries);
    } else if (this.countriesObservable) {
      return this.countriesObservable;
    } else {
//lang is not defined yet it has to be retrieved from storage

      this.countriesObservable = this.http.get(AppSettings.API_URL + '?locale=' + lang).map(json => {
        delete this.countriesObservable; // when the cached countries is available we don't need  reference anymore
        this.countries = json as Country[];
        this.countries = this.countries.sort(function (a, b) { return (a.Name > b.Name) ? 1 : ((b.Name > a.Name) ? -1 : 0); });
        return this.countries;
      }).share();
      return this.countriesObservable;
    }
  }

由于 api 需要语言(lang)并且此信息存储在存储中,可以从存储中检索如下:

  this.storage.get(AppSettings.STORAGE_KEYS.LANGUAGE_APP).then(language=>{
        //here I can use language
      });

现在我被卡住的地方是如何在我从上述承诺中检索语言信息后调用我的 api。我需要确保函数(getCountries)仍然返回它最初返回的 observable。 感谢您的帮助。

有些人建议将它们包装在 Observable.fromPromise 中,我也这样做了,但是这破坏了代码。我一定遗漏了一些我知道的东西。这里是:它是否错过了返回某些东西,在之后发布我的堆栈跟踪代码:

 getCountries(): Observable<Country[]> {
    if (this.countries) {
       return Observable.of(this.countries);
    } else if (this.countriesObservable) {
      return this.countriesObservable;
    } else {
      Observable.fromPromise(this.storage.get(AppSettings.STORAGE_KEYS.LANGUAGE_APP)).subscribe(language=>{
        //here I can use language
        this.countriesObservable = this.http.get(AppSettings.API_URL + '?locale=' + language).map(json => {
          delete this.countriesObservable; 
          this.countries = json as Country[];
          this.countries = this.countries.sort(function (a, b) { return (a.Name > b.Name) ? 1 : ((b.Name > a.Name) ? -1 : 0); });
          return this.countries;
        }).share();
        return this.countriesObservable;
      });
    }
  }



Error: Uncaught (in promise): TypeError: Cannot read property 'subscribe' of undefined
TypeError: Cannot read property 'subscribe' of undefined
    at http://localhost:8100/build/main.js:71:33
    at new t (http://localhost:8100/build/polyfills.js:3:20886)
    at UtilsProvider.webpackJsonp.10.UtilsProvider.getCountryById (http://localhost:8100/build/main.js:70:16)
    at MyApp.webpackJsonp.851.MyApp.updateUserInfo (http://localhost:8100/build/main.js:10067:47)
    at http://localhost:8100/build/main.js:9774:23
    at SafeSubscriber.schedulerFn [as _next] (http://localhost:8100/build/vendor.js:4004:36)
    at SafeSubscriber.__tryOrUnsub (http://localhost:8100/build/vendor.js:16987:16)
    at SafeSubscriber.next (http://localhost:8100/build/vendor.js:16934:22)
    at Subscriber._next (http://localhost:8100/build/vendor.js:16874:26)
    at Subscriber.next (http://localhost:8100/build/vendor.js:16838:18)
    at c (http://localhost:8100/build/polyfills.js:3:19132)
    at c (http://localhost:8100/build/polyfills.js:3:18841)
    at http://localhost:8100/build/polyfills.js:3:19613
    at t.invokeTask (http://localhost:8100/build/polyfills.js:3:15040)
    at Object.onInvokeTask (http://localhost:8100/build/vendor.js:4238:33)
    at t.invokeTask (http://localhost:8100/build/polyfills.js:3:14961)
    at r.runTask (http://localhost:8100/build/polyfills.js:3:10214)
    at o (http://localhost:8100/build/polyfills.js:3:7274)
    at e.invokeTask [as invoke] (http://localhost:8100/build/polyfills.js:3:16203)
    at p (http://localhost:8100/build/polyfills.js:2:26993)

【问题讨论】:

  • 你甚至需要这样做吗 - this.storage.get(AppSettings.STORAGE_KEYS.LANGUAGE_APP).then(language=>{ //这里我可以使用语言 });你不能这样做吗?storage.get(AppSettings.STORAGE_KEYS.LANGUAGE_APP)?

标签: javascript angular typescript observable angular-promise


【解决方案1】:

只需使用 Observable.fromPromise。所以在你的情况下,它会是

getCountries(): Observable<Country[]> {
    if (this.countries) {
       return Observable.of(this.countries);
    } else if (this.countriesObservable) {
      return this.countriesObservable;
    } else {
      return Observable.fromPromise(this.storage.get(AppSettings.STORAGE_KEYS.LANGUAGE_APP)).mergeMap(language=>{
        //here I can use language
        this.countriesObservable = this.http.get(AppSettings.API_URL + '?locale=' + language).map(json => {
          delete this.countriesObservable; // when the cached countries is available we don't need the  reference anymore
          this.countries = json as Country[];
          this.countries = this.countries.sort(function (a, b) { return (a.Name > b.Name) ? 1 : ((b.Name > a.Name) ? -1 : 0); });
          return this.countries;
        }).share();
        return this.countriesObservable;
      });
    }
  }

【讨论】:

  • 所以您的意思是像这样更改我的功能,将其添加到我的问题详细信息中,因为我无法在评论中添加它。
  • 我在帖子中添加了详细信息。谢谢
  • 感谢您的提示,但是我的代码仍然损坏我添加了有问题的详细信息。任何线索为什么我会收到该错误?
  • 看这里的链接->js-tutorials.com/javascript-tutorial/…。如果您从本地存储中获取数据,为什么它必须是异步的,即 Promise?
  • 是的,这是承诺。库中的定义是这样的: Storage.prototype.get = function (key) { return this._dbPromise.then(function (db) { return db.getItem(key); }); };
【解决方案2】:

任何 Promise 都可以(很容易)通过 Observable.fromPromise() 转换为 Observable

Observable.fromPromise(this.storage.get(AppSettings.STORAGE_KEYS.LANGUAGE_APP))
.subscribe((language) => {
    //here you can use language
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    • 2018-11-25
    • 1970-01-01
    • 2020-07-14
    • 1970-01-01
    • 2021-02-04
    相关资源
    最近更新 更多