typescript 在服务函数上使用装饰器时,subscribe中next的值变为未定义

eoigrqb6  于 2023-06-24  发布在  TypeScript
关注(0)|答案(1)|浏览(152)

我试图将HTTP响应中的所有日期转换为实际的Date对象,使用装饰器和moment,并以this guide为灵感。
我能够转换实际的日期,并在整个转换过程中正确地记录响应和转换模型的值。
当尝试使用/订阅转换后的响应时,我的问题就出现了。当decorator出现在调用后端的函数上时,该调用中subscribenext参数的值变为undefined
_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) {
  console.log('descriptor A', descriptor);
  const originalMethod = descriptor.value;
  descriptor.value = function () {
    return originalMethod.apply(this).pipe(
      map((obj: PaginationResponse<BaseModel>) => {
        obj.data?.forEach((model:BaseModel) => {
          Object.assign({}, model, stringToDate(model)) // correct dates in console
        });
      })
    )
  }
  console.log('descriptor B', descriptor); // same console output as descriptor A
  return descriptor;
}

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

function stringToDate(obj:any) {
  return Object.keys(obj)
    .filter((key) => obj[key] && isDate(obj[key]))
    .map((key) => { obj[key] = moment(obj[key]).toDate() })
}

在相关的服务类中

@TransformPaginationResponseDates
getPaginatedList():Observable<PaginationResponse<Timer>> {
    return this.http.get<PaginationResponse<Timer>>(`${environment.apiUrl}/timer/list`);
}

在相关组件中

this.timerService.getPaginatedList().pipe(first()).subscribe(paginationResponse => {
  console.log(paginationResponse); // undefined
});

paginationResponse的值在没有decorator的情况下与预期的一样,但是当decorator被用于上面的函数时,undefined的值是undefined
然而,在这方面,

const p = this.timerService.getPaginatedList().pipe(first()).subscribe();
console.log(p);

在这两种情况下都显示类型为SafeSubscriber
_models/paginationResponse.ts(截断)

export class PaginationResponse<T> {
  currentPage?: number;
  data?: Array<T>
  ...
}

_models/timer.ts

import {BaseModel} from "@app/_models/basemodel";

export class Timer extends BaseModel{
  name?: string;
  startedAt?:Date;
}

其中服务器已响应

...
'startedAt' => $this->getStartedAt()->format(DateFormat::ISO_8601->value) // 'c'
...
rryofs0p

rryofs0p1#

在代码中有错误。1:decorator内部的map没有返回任何内容。有很多方法可以解决这个问题,例如

map((obj: PaginationResponse<BaseModel>) => {
        return obj.data?.map((model:BaseModel) =>
          Object.assign({}, model, stringToDate(model)) // correct dates in 
        );
      })

2:stringToDate方法返回数组而不是对象。固定版本:

function stringToDate(obj:any) {
  Object.keys(obj)
    .filter((key) => obj[key] && isDate(obj[key]))
    .map((key) => { obj[key] = moment(obj[key]).toDate() })
  return obj;
}

相关问题