Angular 6 HttpClient.get Observable不分配值

时间:2018-07-12 22:01:27

标签: angular6 angular-httpclient rxjs6

我想答案将非常明显,但仍然回避了我。我对使用可观察对象是新手,现在我面临着从中分配值的问题。如果我将其(this._apps)定义为Observable并使用订阅从视图向服务进行查询,我就取得了成功(但是我的想法是令人费解的(映射内的三个层次只是为了返回数组的另一个Observable,然后另一个用于订阅前一个函数以分配变量的函数,以及另一个在视图中进行订阅以最终显示信息的函数),效率低下,最重要的是,我无法再次“正确”使用它。任务很简单。给定应用程序类

export class Application {
  name: string;
  baseUrl: string;
  deprecated: boolean;
}

和服务(只是相关代码)

private _apps: Application[] = [];

constructor(private _http: HttpClient) {
  this.getAllApplications().subscribe(apps => {
    console.log('Apps subscriber');
    this._apps = apps;
    console.log('Apps subscriber Ends ' + apps);
  },
  err => {
    console.log(err.status); // 401
    console.log(err.error.error); // undefined
    console.log(JSON.parse(err.error).error); // unauthorized
  });
}

private getAllApplications() {
  return this._http.get<Application[]>('http://development:4300/api/v1/apps');
}

从构造函数中触发了从WebAPI获取信息的函数,并且远程调用成功,但是如果我尝试从代码中的任何位置调用变量this._apps,则该变量为空数组。我无法确定订阅函数中参数“ apps”的类型,但是由于某种原因,无法分配它,给出的最佳答案是它是我尝试的一个函数(请参阅我的第一个更新)。当前,它在控制台“ [object Object]”中返回,但是apps [0]给出了undefined,因此它是一个空数组。

这是控制台输出,仅启动应用程序:

Angular在开发模式下运行。调用enableProdMode()以启用生产模式。 刷新的应用程序缓存调用http://development:4300/api/v1/atbc-apps 应用订阅者 Apps订阅者结束[对象对象]

我尝试过this solution的许多我忘记的事情(使用更现代的HttpClient代替以前使用的Http),那么我在做什么错呢?

更新1

我将构造函数更改为此:

constructor(private _http: HttpClient) {
  this.getAllApplications().subscribe(apps => {
    console.log('apps length ' + apps.length);
    this._apps = apps;  // Remember private _apps: Application[] = [];
    console.log('Apps subscriber Ends ' + apps.toString);
  },
    err => {
      console.log(err.status); // 401
      console.log(err.error.error); // undefined
      console.log(JSON.parse(err.error).error); // unauthorized
    });
}

以及在其中调用的函数的声明:

private getAllApplications(): Observable<Application[]> {
   // the exactly the same as before
}

现在我从控制台获得了这个信息:

应用程序长度未定义

Apps订户端     function () { if (this instanceof Promise) { return PROMISE_OBJECT_TO_STRING; } return originalObjectToString.apply(this, arguments); }

那是我在说的功能。关于为什么即使没有错误(编译时也没有运行时)为什么返回对象不是真正的Application数组的任何想法?

2 个答案:

答案 0 :(得分:0)

更改此行:

private _apps: Application[] = [];

收件人:

_apps: Application[] = [];

默认情况下将其公开。然后此行将看到它:

this._apps = apps;

答案 1 :(得分:0)

最后,我认为使用Observables是一种心态,并且我尝试构建一种缓存,因此,我能做到的唯一方法(让我知道是否有更好的方法)是使用视图填写缓存。我不能从服务本身做到这一点,因为从视图中调用函数是同步的,并且要填充数组是异步的。因此,我必须创建一个公共的setApplicationCache过程,该过程在从视图中调用该服务后将被填充,该过程将调用setApplicationCache(Application [])函数,其余的工作正常,因为它仅需要缓存来执行过滤和其他操作或使用它从其他页面开始,没有一次又一次地调用数据库。

这是第一个视图(主页)中的代码

ngOnInit() {
  this._myService.getAllApplications().subscribe(arrObjApps => {
  this._myService.setApplicationsCache(arrObjApps)
  this.listApps = this._myService.getApplications(true);
});    

该服务具有以下功能:

  private _apps: Application[] = [];

  getAllApplications(): Observable<Application[]>  {
    return this._http.get('http://development:4300/api/v1/atbc-apps').pipe(
      map( (response: Response) => {
        let results = response.json().data.map( app => {
        return new Application(app.name, app.baseUrl, app.deprecated);
      });
      return results;
    })
  );
}

getApplication(appName: string): Application {
  return this._apps.find(app => app.name == appName);
}

getApplications(onlyActives: boolean): Application[] {
  if (onlyActives) {
    return this._apps.filter(app => app.deprecated == false);
  } else {
    return this._apps;
  }
}

正如我所说,解决方案应该很明显。再次需要使用可观察对象的异步思维方式。