Я довольно глубоко объявил interface
, что выглядит примерно так:
export interface Job {
JobId: JobId; // type JobId = string
UserId: UserId; // type UserId = string
JobName: string;
AudioFile: JobAudioFile; // this is an interface
Status: JobStatus; // this is an enum
Tracks: JobTracks[]; // 'JobTracks' is an enum
Results: JobResults; // this is an interface
Timestamps: JobTimestamps // interface
}
Большинство членов этого интерфейса сами являются интерфейсами, с общей архитектурой, следующей этой схеме использования перечислений, строк, массивы и больше интерфейсов.Весь код написан как TypeScript, передан в JS и загружен в AWS как JS.(Узел 8.10 работает на AWS)
В одном месте кода мне нужно сделать глубокую копию экземпляра Job
, который был передан в качестве параметра функции:
export const StartPipeline: Handler = async (
event: PipelineEvent
): Promise<PipelineEvent> => {
console.log('StartPipeline Event: %o', event);
const newBucket = await copyToJobsBucket$(event.Job);
await deleteFromOriginalBucket$(event.Job);
console.log(`Job [${event.Job.JobId}] moved to Jobs bucket: ${newBucket}`);
event.Job.AudioFile.Bucket = newBucket;
event.Job.Status = Types.JobStatus.Processing;
// update the job status
// VVV PROBLEM OCCURS HERE VVV
const msg: Types.JobUpdatedMessage = new Types.JobUpdatedMessage({ Job: Object.assign({}, event.Job) });
await Send.to$(event.Job.UserId, msg);
return { ...event };
};
Определение JobUpdatedMessage
:
export class JobUpdatedMessage extends BaseMessage {
constructor(payload: { Job: Types.Job }) {
console.log('Incoming: %o', payload);
const copy: object = { ...payload.Job };
// VVV PROBLEM ON NEXT LINE VVV
const filtered = JobUtils.FilterJobProperties(copy as Types.Job);
super(MessageTypes.JobUpdated, filtered);
}
}
Проблема в том, что после вызова JobUtils.FilterJobProperties
, payload.Job
также был видоизменен нежелательным и неожиданным образом.
Вот реализация JobUtils.FilterJobProperties
:
export const FilterJobProperties = (from: Types.Job): Types.Job => {
const fieldsToRemove: string[] = [
'Transcripts.GSTT',
'Transcripts.WSTT',
'Transcripts.ASTT',
'TranscriptTracks',
'Transcripts.Stream.File',
'Transcripts.Stream.State',
'AudioFile.Bucket',
'AudioFile.S3Key',
];
let job: Types.Job = { ...from }; // LINE ONE
fieldsToRemove.forEach(field => _.unset(job, field)); // LINE TWO
return job;
};
(здесь я использую библиотеку lodash)
Линейный рынок 'LINE TWO' также изменяет параметр функции from
,хотя в «LINE ONE» я делаю то, что я считаю глубоким клоном from
.
, я знаю, что это так, потому что если я изменю «LINE ONE» на:
// super hard core deep cloning
let job: Types.Job = JSON.parse(JSON.stringify(from));
... все работает как положено.from
не видоизменяется, результирующий JobUpdatedMessage
соответствует ожидаемому, а у параметра StartPipeline
*1034* нет набора свойств, удаленных из event.Job
.
Я боролся с часамина этом, включая повторное изучение всего, что я знал о клонировании объектов в Es6, используя оператор распространения.
Почему 'LINE ONE' также поменял вход?