如何从ngrx存储区中的select获取错误?

时间:2019-01-23 19:14:17

标签: angular ngrx

假设我的商店可以使用一些操作:Load,LoadFail和LoadSuccess。我所有的动作都很简单,LOAD = "load"LOAD_FAIL = "load failed"LOAD_SUCCESS = "load success"我有一个简单的reducer可以打开这些,就像这样:

export function reducer(state: State = initialState, action: Actions): State {
    switch (action.type) {
        case Actions.LOAD: {
            console.log("Actions.LOAD");
            return state;
        }
        case Actions.LOAD_FAIL: {
            console.log("Actions.LOAD_FAIL");
            store.error = action.payload;
            return state;
        }
        case Actions.LOAD_SUCCESS: {
            console.log("Actions.LOAD_SUCCESS");
            state.data = action.payload;
            return state;
        }
        default: {
            return state;
        }
    }
}

我有一个可以处理负载分配的效果类:

@Injectable()
export class TestersEffects {
    constructor(
        private service: MyHttpService,
        private actions$: Actions
    ) {}

    @Effect() load$ = this.actions$.pipe(
        ofType(Actions.LOAD),
        switchMap(
            action => {
                return this.service.load().pipe(
                    map(data => {
                        console.log("load$ fired");
                        return new TestersActions.LoadSuccess(data);
                    }),
                    catchError(error => {
                        console.log("error");
                        return of (new Actions.LoadFail(error));
                    })
                )
            }
        )
    );
}

最后,我正在使用所有这些内容:

export class MyClass implements OnInit {
    data: any;

    constructor(private store: Store<AppState>) {}

    ngOnInit() {
        this.store.dispatch(new Actions.Load());
        this.store.select(store => store.State).subscribe(
            data => this.data = data,
            error => this.handleError(error)
        );
    }

    handleError(error) {
        //Whatever I'll do to handle this error
    }
}

当我请求的服务器响应时,此代码可以正常工作。但是,我需要处理它没有响应的情况。我假设我只是不太了解ngrx / store的流程,无法完全理解如何获取错误,但是我很茫然。当我调试代码时,我的效果类中的catchError会触发并发送LoadFail操作,减速器会捕获该操作,设置错误并返回状态。但是,在我订阅的MyClass方面,我什么也看不到。我认为我肯定在这里缺少一些关键的东西,但是我所有的Google搜寻专业知识都让我无所事事,并且我想我会勇敢地利用Stack Overflow并乞求它在此问题上的智慧。

tl; dr:当服务器响应时,我的商店工作正常,但是当服务器没有响应时,我的错误不会发送到可观察到的商店状态订阅。

2 个答案:

答案 0 :(得分:0)

我认为您在这里遇到的问题是,您似乎在尝试将错误作为可观察链中的错误推入整个商店,而不是使错误成为您状态的另一部分。

您正在寻找的东西更像是

// Add a property to your state object to hold errors...
interface State {
  // ...
  error: Error | null;
}

// Then in your reducer...
case Actions.LOAD_FAIL: {
  console.log("Actions.LOAD_FAIL");
  return { ...state, error: action.error };
}

然后,在您的订阅中,查询存储中此error字段的值将使您知道请求是否失败以及是否调度了任何错误(我建议为此选择一个可以直接订阅的选择器)。

我也没有亲自尝试过,但是我有一种尝试以这种方式对可观察到的商店进行错误处理会杀死您应用程序中的商店的信息,因此请不要尝试。

答案 1 :(得分:0)

我知道了。我将进行类比,然后从技术上进行解释。

比方说,您有一辆汽车像所有汽车一样拥有自己的独特VIN。在那辆车上,您可以坐几个座位。当车到达时,您只真正在乎车内的人,而不必关心车本身。从本质上讲,在我的原始示例中发生的是,好像我在检查它是否是新车,而不是新人。因此,为了使系统正常工作,我不得不检查人员,而不是汽车。

这是技术性的。当比较两个对象时,如果它们的引用不同,则无论它们包含什么数据,它们都不是同一对象。就我而言,我想观察状态对象的变化。之所以不起作用,是因为尽管内部数据发生了变化,状态对象的引用却从未改变那我该如何解决?好吧,有两种解决方法。如果要继续观察状态对象本身的变化,则需要在reducer中使用要提供的新数据重新分配它。否则,如果您只想观察变化/错误,则需要观察您关心的每个变量。

从本质上讲,它可以归结为:

interface Person {
    name: string;
    id: number;
}

function comparePeople() {
    var p1: Person = { name: "John", id: 1 }
    var p2: Person = { name: "James", id: 2 }
    var p3: Person = { name: "John", id: 1 }

    console.log(`p1 === p1 ? ${p1 === p1});
    console.log(`p1 === p2 ? ${p1 === p2});
    console.log(`p1 === p3 ? ${p1 === p3});
}