You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular集成Discord OAuth2报错:Observable<Object>不存在body属性

解决Discord OAuth2集成时“Property 'body' does not exist on type 'Observable'”错误

我在制作Discord Bot仪表盘并集成Discord OAuth2时,参考教程编写了如下代码,但运行时出现错误:Property 'body' does not exist on type 'Observable<Object>'。

我的代码

async getJSONResponse(body) {
    let fullBody = '';

    for await(const data of body) {
      fullBody += data.toString();
    }

    return JSON.parse(fullBody)
  }

  async getAccessToken(code) {
    if (code) {
      try {
        let body = new URLSearchParams();
        body.append('client_id', environment.discord.clientId)
        body.append('client_secret', environment.discord.clientSecret)
        body.append('code', code)
        body.append('grant_type', 'authorization_code')
        body.append('redirect_uri', environment.discord.redirect)
        body.append('scope', 'identify')

        let options = {
          headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
        };

        const tokenResponseData = await this.http.post('https://discord.com/api/oauth2/token', body.toString(), options)
  
        const oauthData = await this.getJSONResponse(tokenResponseData.body)
        console.log(oauthData)

      } catch(err) {
        console.error('an error')
        console.error(err)
      }
    }
  }

问题原因

你使用的是Angular的HttpClient,它的post方法返回的是Observable,而教程里的代码大概率基于Node.js的fetch API或其他Promise式HTTP客户端,这类客户端返回的响应对象带有body属性,二者的返回类型完全不同,这就是报错的根源。

解决方案

方案1:使用firstValueFrom转换为Promise(Angular 12+推荐)

Angular的Observable可以通过firstValueFrom转换为Promise,配合async/await使用,同时HttpClient会自动解析JSON响应,不需要手动处理:

// 先导入firstValueFrom
import { firstValueFrom } from 'rxjs';

async getAccessToken(code) {
  if (code) {
    try {
      let body = new URLSearchParams();
      body.append('client_id', environment.discord.clientId)
      body.append('client_secret', environment.discord.clientSecret)
      body.append('code', code)
      body.append('grant_type', 'authorization_code')
      body.append('redirect_uri', environment.discord.redirect)
      body.append('scope', 'identify')

      let options = {
        headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
      };

      // 转换Observable为Promise
      const oauthData = await firstValueFrom(
        this.http.post('https://discord.com/api/oauth2/token', body.toString(), options)
      );
      console.log(oauthData);
      // 无需再调用getJSONResponse,HttpClient已自动解析JSON
    } catch(err) {
      console.error('出错了', err);
    }
  }
}

方案2:直接订阅Observable(传统Angular写法)

如果不想用async/await,可以直接订阅Observable获取响应数据:

async getAccessToken(code) {
  if (code) {
    let body = new URLSearchParams();
    body.append('client_id', environment.discord.clientId)
    body.append('client_secret', environment.discord.clientSecret)
    body.append('code', code)
    body.append('grant_type', 'authorization_code')
    body.append('redirect_uri', environment.discord.redirect)
    body.append('scope', 'identify')

    let options = {
      headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
    };

    this.http.post('https://discord.com/api/oauth2/token', body.toString(), options)
      .subscribe({
        next: (oauthData) => {
          console.log(oauthData);
        },
        error: (err) => {
          console.error('出错了', err);
        }
      });
  }
}

内容的提问来源于stack exchange,提问作者codepip55

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 01:24:30