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

Angular中使用装饰器后,订阅服务函数的next参数变为undefined

问题分析与解决:HTTP响应日期转换后订阅值为undefined

核心问题

你的装饰器中使用RxJS map操作符时,没有返回处理后的对象,导致流中传递的值变为undefined,最终订阅时拿到的就是undefined。此外还有两处冗余/错误的代码逻辑需要修正:

  • map操作内处理完obj后未返回,RxJS的map需要返回新值传递给下游
  • stringToDate函数中用map遍历键值对不合适(map用于生成新数组,此处是修改原对象,应改用forEach)
  • Object.assign({}, model, stringToDate(model))属于冗余代码,因为stringToDate已经直接修改了原model对象

修正后的代码

_transformers/TransformDate.ts

import { map } from "rxjs/operators";
import * as moment from "moment";
import { PaginationResponse } from "@app/_models/paginationResponse";
import { BaseModel } from "@app/_models/basemodel";

export function TransformPaginationResponseDates(target: any, key: any, descriptor: any) {
  const originalMethod = descriptor.value;
  descriptor.value = function () {
    return originalMethod.apply(this).pipe(
      map((obj: PaginationResponse<BaseModel>) => {
        // 处理数据中的日期,直接修改原对象
        obj.data?.forEach((model: BaseModel) => {
          stringToDate(model);
        });
        // 关键:返回处理后的对象,让流继续传递
        return obj;
      })
    )
  }
  return descriptor;
}

const isDate = (s: string) => moment(s, moment.ISO_8601, true).isValid();

function stringToDate(obj: any) {
  Object.keys(obj)
    .filter((key) => obj[key] && isDate(obj[key]))
    // 改用forEach修改原对象,map是生成新数组,此处不需要返回数组
    .forEach((key) => { obj[key] = moment(obj[key]).toDate() })
}

验证效果

修改后,调用服务的订阅代码:

this.timerService.getPaginatedList().pipe(first()).subscribe(paginationResponse => {
  console.log(paginationResponse); // 正常输出处理后的PaginationResponse对象,startedAt已转为Date类型
});

此时订阅能正确拿到处理后的响应对象,同时日期字符串已被转换为Date类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 10:27:34