Как получить ошибки от выбора в магазине ngrx? - PullRequest
0 голосов
/ 23 января 2019

Допустим, у меня есть несколько действий, которые мой магазин может использовать: Load, LoadFail и LoadSuccess.Все мои действия очень просты, LOAD = "load", LOAD_FAIL = "load failed" и LOAD_SUCCESS = "load success" У меня есть простой редуктор, который включает их, например, так:

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 оставили меня с пустыми руками, и я решил, что буду храбрым переполнением стека и буду просить его мудрости по этому вопросу.

tl; dr: Мой магазинработает нормально, когда сервер отвечает, но когда нет, мои ошибки не отправляются на подписку наблюдаемого состояния магазина.

Ответы [ 2 ]

0 голосов
/ 25 января 2019

Я понял это. Я собираюсь привести это по аналогии, а затем объяснить это технически.

Допустим, у вас есть определенный автомобиль с собственным уникальным VIN, как и у всех автомобилей. В этой машине у вас есть несколько мест, в которых могут сидеть люди. Когда машина прибывает, вы действительно заботитесь только о людях, которые находятся внутри нее, а не обязательно о самой машине. По сути, то, что происходит в моем первоначальном примере, заключается в том, что я как будто проверял, была ли это новая машина, а не новые люди. Поэтому, чтобы заставить систему работать, мне нужно было проверять людей, а не машину.

Так что это техническое. Когда вы сравниваете два объекта, если их ссылки не совпадают, то это не один и тот же объект, независимо от данных, которые они содержат. В моем случае я хотел наблюдать изменение в моем объекте состояния. Причина, по которой это не сработало, заключается в том, что ссылка на объект состояния никогда не менялась, , несмотря на изменение внутренних данных . Так как я это исправил? Ну, есть два способа сделать это. Если вы хотите продолжить наблюдать изменения в самом объекте состояния, вам нужно переназначить его в редуктор с новыми данными, которые вы хотите предоставить. В противном случае, если вы хотите наблюдать только изменения / ошибки, вам нужно наблюдать за каждой переменной, о которой вы заботитесь.

По сути, это сводится к тому, как это приравнивается:

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});
}
0 голосов
/ 24 января 2019

Я думаю, что проблема, с которой вы здесь столкнулись, заключается в том, что вы пытаетесь протолкнуть ошибку через свой магазин как ошибку в наблюдаемой цепочке, а не превращаете ошибку в другую часть вашего состояния.

То, что вы ищете, похоже на:

// 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 в магазине, вы узнаете, если запрос не выполнен и возникла какая-либо ошибка (я бы рекомендовал сделать селектор для этого, на который вы можете подписаться напрямую).

Кроме того, я сам не пробовал, но у меня есть ощущение, что попытка ошибиться в хранилище, наблюдаемом таким образом, приведет к уничтожению хранилища в вашем приложении, поэтому на самом деле не следует пытаться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...