【问题标题】:return value from subscribe in service angular 8从服务角度 8 中订阅的返回值
【发布时间】:2019-12-29 03:32:41
【问题描述】:

我有一个服务,它有一种方法可以获取用户的个人资料图像。

users.service.ts

getPictureProfile() {
    const headers = new HttpHeaders({ . . .});
    const options = { headers };
    const body = {...};
    return this.http.post(environment.apiUrl + '/Users/GetPictureProfile', body, options);
}

然后我有一个名为 userHelper 的有用类,它包含一个应该只返回 base64 格式的图像字符串的方法。目的是从任意组件获取图片链,无需再次使用订阅。

user-helper.ts

getPictureProfile(): any {
    return this.usersService.getPictureProfile().subscribe(
      (res: any) => {
        console.log('=================res subscribe=================');
        console.log(res);
        return res;
      },
      err => {
        return '';
      }
    );
  }

最后我有一个组件(目标是我可以在任何组件中使用它),它调用userHelper类方法只是为了获取图像字符串,但它返回一个对象。

  getUserProfile() {
    this.pictureProfile = this.userHelper.getPictureProfile();
    console.log('==========this.pictureProfile==========');
    console.log(this.pictureProfile);
  }

结果如下

如何在不需要重用订阅的情况下获得返回服务的链? (预期的是'================= res subscribe ================='下面的字符串)

如果你想知道为什么我在服务上使用 post 而不是 get 方法,那是因为 owasp 建议在服务中使用 post 方法(尤其是使用 https 更安全一些)。

感谢您的帮助

【问题讨论】:

  • 我在想,在您的 user-helper.ts 'getPictureProfile' 中,不要在那里订阅。换一张地图。然后在您的组件中订阅。
  • 您可以从订阅内部返回,正如其他人所说,您需要使用诸如 map() 之类的管道运算符来根据需要操作数据。 learnrxjs.io/operators/transformation/map.html 。或者只是订阅组件/消费者并在那里相应地处理成功/错误。

标签: angular angular8


【解决方案1】:

您的服务(http 请求)必须返回一个 observable,其中“any”类型是您的响应对象类型。

getPictureProfile(): Observable<any> {
    const headers = new HttpHeaders({ . . .});
    const options = { headers };
    const body = {...};
    const url =  environment.apiUrl + '/Users/GetPictureProfile';

    return this.http.post(url, body, options)
    .pipe(
      map(result => {
        return result;
      })
    );
}

【讨论】:

    【解决方案2】:

    在 user-helper.ts 你不能简单地从订阅中返回一个值,observable 作为异步操作运行并且方法是同步的并且该方法不会等到 observable 返回一个值,你可以更新你的代码来使用async/await 仍然是异步操作,但它看起来像同步流程

    user-helper.ts

    getPictureProfile() {
      this.usersService.getPictureProfile().toPromise() 
    }
    

    组件

      async getUserProfile() {
        this.pictureProfile = await this.userHelper.getPictureProfile();
        console.log('==========this.pictureProfile==========');
        console.log(this.pictureProfile);
      }
    

    如果您不想使用 async/await,则必须确保用户辅助方法返回 observable 而不是在其中订阅。

    user-helper.ts

    
    getPictureProfile(): any {
        return this.usersService.getPictureProfile().pipe(
          tap(res: any) => {
            console.log('=================res subscribe=================');
            console.log(res);
          });
      }
    

    组件

    getUserProfile() {
        this.userHelper.getPictureProfile().subscribe( res =>{
         this.pictureProfile = res;
        console.log('==========this.pictureProfile==========');
        console.log(this.pictureProfile);
    
        });
    
      }
    

    【讨论】:

      【解决方案3】:

      Pipeable 运营商来救援!

      我的建议是使用pipe,这样你就可以这样做:

      getProfilePicture().pipe(map(picture: any)=>{return convertToBase64(picture)});
      

      您的 getProfilePicture() 方法应该返回 Observable 原样,而您的助手 convertToBase64() 只接收一个普通参数(不是 Observable)并相应地返回 base64

      【讨论】: