Angular - 调度动作时出现“TypeError:无法冻结”

Posted

技术标签:

【中文标题】Angular - 调度动作时出现“TypeError:无法冻结”【英文标题】:Angular - "TypeError: Cannot freeze" when dispatching an action 【发布时间】:2019-02-27 20:23:35 【问题描述】:

我正在开发一个使用 ngrx 商店和效果的 Angular 应用程序。我明白了

“类型错误:无法冻结”

从我的组件调度操作时出错。我为文件上传功能编写了它。我认为我正在改变状态,但无法弄清楚在哪里以及如何解决它。 这是我的详细代码:

Actions:

export enum FileUploadActionTypes 
    UploadFile = '[File Upload] Upload File',
    UploadFileSuccess = '[File Upload] Upload File Success',
    UploadFileFailure = '[File Upload] Upload File Failure'


export class UploadFile implements Action 
    readonly type = FileUploadActionTypes.UploadFile;

    constructor(public payload: any) 


export class UploadFileSuccess implements Action 
    readonly type = FileUploadActionTypes.UploadFileSuccess;

    constructor(public payload: any) 


export class UploadFileFailure implements Action 
    readonly type = FileUploadActionTypes.UploadFileFailure;

    constructor(public payload: any) 


export type FileUploadActionsUnion = UploadFile | UploadFileSuccess | UploadFileFailure;

Service:

export class FileUploadService 
    constructor(private httpClient: HttpClient) 

    
    uploadFile(file: any): Observable<any> 
        return this.httpClient.post<any[]>('/api-url/', file);
    

Effect:

@Effect()
uploadFile$ = this.actions$.pipe(
    ofType<UploadFile>(FileUploadActionTypes.UploadFile),
    mergeMap(action => this.fileUploadService.uploadFile(action.payload).pipe(
        map(result => new UploadFileSuccess(result)),
        catchError(error => of(new UploadFileFailure(error)))
    ))
)

Reducer:

export interface State 
    fileUploadSuccessResponse: any,
    fileUploadFailureResponse: any


export const initialState = 
    fileUploadSuccessResponse: null,
    fileUploadFailureResponse: null


export const getFileUploadSuccessResponse = state => state.fileUploadSuccessResponse;
export const getFileUploadFailureResponse = state => state.fileUploadFailureResponse;

export function reducer(state: State = initialState, action: FileUploadActionsUnion):State 
    switch(action.type) 
        case FileUploadActionTypes.UploadFile: 
            return 
                ...state
            
        
        case FileUploadActionTypes.UploadFileSuccess: 
            return 
                ...state,
                fileUploadSuccessResponse: action.payload
            
        
        case FileUploadActionTypes.UploadFileFailure: 
            return 
                ...state,
                fileUploadFailureResponse: action.payload
            
        
        default: 
            return state;
        
    

【问题讨论】:

payload 长什么样子? 【参考方案1】:

看来您正在使用ngrx-store-freeze npm 包。此软件包可确保您对商店所做的任何更新都不会直接发生变化。此过程的一部分是将Object.freeze() 应用于您尝试调度的操作的payload 对象。即this.store.dispatch(new UploadFiles(file))

&lt;input type="file"&gt; 控件的默认行为是将其值保存为FileList 对象。因为此对象是原始数据类型,javascript 会将其视为只读,从而阻止您写入它的属性。这也解释了为什么 Object.freeze() 会失败,因为它无法对只读数据类型应用冻结。

我最近在使用 NGRX 和 &lt;input type="file"&gt; 表单控件时遇到了同样的问题。解决方法是在分派到商店之前将 FileList 克隆到一个新对象中。

onChange(control: FormControl) 
  const primitiveFileList: FileList = control.value;
  const clonedFiles =  ...primitiveFileList ;
  this.store.dispatch(new UploadFiles(clonedFiles));

如果其他人知道这种方法的任何潜在缺陷,我将不胜感激。

【讨论】:

在我的例子中,只是克隆 FileList 对象删除了length 属性和item() 函数。所以我需要自己给clone加上length属性,以后还要用[i]代替item(i)

以上是关于Angular - 调度动作时出现“TypeError:无法冻结”的主要内容,如果未能解决你的问题,请参考以下文章

启动时出现 Angular 8 错误

调度传入 RPC 调用时出现异常

使用 Angular 材质定义自定义主题时出现 SassError

为啥在尝试升级 Angular 时出现“没有导出成员”错误?

调度由 saga 中的 createAsyncThunk 创建的操作时出现打字稿错误

添加第一个 dag 时出现 Cloud Composer 调度程序错误