我们刚刚将其中一个应用程序升级到Angular 5,并开始转换为rxjs v5.5中引入的lettable 运算符.
因此,我们使用.pipe()
运算符将可观察的管道重写为新语法.
我们之前的代码看起来像这样,如果抛出错误,则.catch()
内部.switchMap()
不会中断效果的运行.
@Effect()
loadData$ = this.actions$
.ofType(LOAD_DATA)
.map((action: LoadData) => action.payload)
.withLatestFrom(this.store.select(getCultureCode))
.switchMap(([payload, cultureCode]) => this.dataService.loadData(payload, cultureCode)
.map(result => {
if (!result) {
return new LoadDataFailed('Could not fetch data!');
} else {
return new LoadDataSuccessful(result);
}
})
.catch((err, caught) => {
return Observable.empty();
});
);
Run Code Online (Sandbox Code Playgroud)
如果在调用中抛出错误dataService
,它将被捕获并处理(简化了错误处理).
有了新的语法和用法.pipe()
,我们现在有了这个
@Effect()
loadData$ = this.actions$
.ofType(LOAD_DATA)
.pipe(
map((action: LoadData) => action.payload),
withLatestFrom(this.store.select(getCultureCode)),
switchMap(([payload, cultureCode]) => this.dataService.loadData(payload, cultureCode)),
map(result => …
Run Code Online (Sandbox Code Playgroud) 我需要在调用 API 请求后分派多个操作。我目前正在使用此代码在 API 请求完成后分派一个操作:
changeStatus$ = createEffect(() =>
this.actions$.pipe(
ofType(fromJtDetail.changeStatus),
switchMap(action =>
this.jtDetailService.changeStatus(action.entity,action.jobTicketId).pipe(
map(res => fromJtDetail.statusChanged({changedStatus: action.entity.newStatus})),
catchError(error => EMPTY)
))));
Run Code Online (Sandbox Code Playgroud)
在这个效果中调度更多的动作很重要,不能为此编写另一个效果。
我遇到了ngrx商店的问题,没有调度一个应该处理它的效果的动作.
以下是尝试发送的组件:
signin() {
this.formStatus.submitted = true;
if (this.formStatus.form.valid) {
this.store.dispatch(new StandardSigninAction(this.formStatus.form.value.credentials));
}
}
Run Code Online (Sandbox Code Playgroud)
行动:
export const ActionTypes = {
STANDARD_SIGNIN: type('[Session] Standard Signin'),
LOAD_PERSONAL_INFO: type('[Session] Load Personal Info'),
LOAD_USER_ACCOUNT: type('[Session] Load User Account'),
RELOAD_PERSONAL_INFO: type('[Session] Reload Personal Info'),
CLEAR_USER_ACCOUNT: type('[Session] Clear User Account')
};
export class StandardSigninAction implements Action {
type = ActionTypes.STANDARD_SIGNIN;
constructor(public payload: Credentials) {
}
}
...
export type Actions
= StandardSigninAction
| LoadPersonalInfoAction
| ClearUserAccountAction
| ReloadPersonalInfoAction
| LoadUserAccountAction;
Run Code Online (Sandbox Code Playgroud)
效果:
@Effect()
standardSignin$: Observable<Action> = this.actions$ …
Run Code Online (Sandbox Code Playgroud) 我有这样的副作用:
@Effect()
FetchAllOrders$ = this.actions$
.ofType(SalesOrderActions.FETCH_ALL_ORDERS)
.switchMap((action: Action) => {
return this.soApiService.getUsersSalesOrders(action.payload);
})
.map((salesOrders: ListDto<SalesOrderList>) => this.actions.fetchAllOrdersSuccess(salesOrders));
Run Code Online (Sandbox Code Playgroud)
我想在效果开始时显示加载符号并在结尾隐藏它.
我创建了一组独立的Actions,Reducers和store状态来处理显示加载符号.
export class BusyActions {
static SHOW_SPINNER = "SHOW_SPINNER";
static HIDE_SPINNER = "HIDE_SPINNER";
showSpinner(): Action {
return { type: BusyActions.SHOW_SPINNER };
}
hideSpinner(): Action {
return { type: BusyActions.HIDE_SPINNER };
}
export const BusyState: IBusyState = {
visible: false,
busy: false
};
Run Code Online (Sandbox Code Playgroud)
我这样做是因为加载状态需要与其他模块,状态等共享.
如何从副作用中调用我的BusyActions?我需要在开始时调用SHOW_SPINNER,最后调用HIDE_SPINNER.
我做得对吗?或者有更好的方法来处理这个问题吗?
我对这个问题有自己的看法,但最好仔细检查并确定.感谢您的关注并尝试提供帮助.这里是:
想象一下,我们正在调度一个触发一些状态变化的动作,并且还附加了一些效果.所以我们的代码必须做两件事 - 改变状态并做一些副作用.但这些任务的顺序是什么?我们是在同步吗?我相信,首先,我们改变状态,然后做副作用,但有可能,这两个任务之间可能会发生其他事情吗?像这样:我们改变状态,然后在我们之前做过的HTTP请求上得到一些响应并处理它,然后做副作用.
[编辑:]我决定在这里添加一些代码.而且我也简化了它.
州:
export interface ApplicationState {
loadingItemId: string;
items: {[itemId: string]: ItemModel}
}
Run Code Online (Sandbox Code Playgroud)
操作:
export class FetchItemAction implements Action {
readonly type = 'FETCH_ITEM';
constructor(public payload: string) {}
}
export class FetchItemSuccessAction implements Action {
readonly type = 'FETCH_ITEM_SUCCESS';
constructor(public payload: ItemModel) {}
}
Run Code Online (Sandbox Code Playgroud)
减速器:
export function reducer(state: ApplicationState, action: any) {
const newState = _.cloneDeep(state);
switch(action.type) {
case 'FETCH_ITEM':
newState.loadingItemId = action.payload;
return newState;
case 'FETCH_ITEM_SUCCESS':
newState.items[newState.loadingItemId] = action.payload;
newState.loadingItemId = null;
return newState;
default: …
Run Code Online (Sandbox Code Playgroud) 我正在使用带有Angular和ngrx/store和ngrx/effects的redux风格的状态管理设计.每当我不从效果中返回动作时,我都会收到错误:
Cannot read property 'type' of undefined
Run Code Online (Sandbox Code Playgroud)
我研究了这个问题,发现在榆树架构中有一种称为"noop"的动作,当你不想用你的效果链接另一个动作时,你可以调用任何东西.在任何地方召唤这种noop行动对我来说都是非常重复的.我想知道这是否是一个不好的做法.有没有理由你不能产生不返回动作的效果?效果的意图总是有1个动作引发另一个动作吗?我想知道我是否误解了如何使用效果.
谢谢!
可以影响像Promise.all这样的两个动作吗?例:
@Effect()
pulic addUser() {
return this.actions$.ofType(user.ADD)
.switchMap(() => {
return this.userService.add();
})
.map(() => {
return new user.AddSuccessAction();
});
}
@Effect()
pulic addUserOptions() {
return this.actions$.ofType(userOptions.ADD)
.switchMap(() => {
return this.userOptionsService.add();
})
.map(() => {
return new userOptions.AddSuccessAction();
});
}
@Effect()
public complete() {
return this.actions$.ofType(user.ADD_SUCCESS, userOptions.ADD_SUCCESS)
// how to make it works like Promise.all ?
.switchMap(() => {
return this.statisticService.add();
})
.map(() => {
return new account.CompleteAction();
});
}
Run Code Online (Sandbox Code Playgroud)
更新 我想要实现的是Promise.all的simillar行为.如何并行调度两个效果,等待所有效果都解决,然后发出第三个动作.像https://redux-saga.js.org/docs/advanced/RunningTasksInParallel.html这样的承诺它是非常明显的:
Promise.all([fetch1, fetch2]).then(fetch3);
Run Code Online (Sandbox Code Playgroud)
是否有可能在ngrx /效果?或者在ngrx /效果中它是错误的方式? …
我已经开发了一些实现 Redux (NgRx) 的 Angular 应用程序。我无法弄清楚我当前项目的问题。
行动:
export class GetUserFromStorage implements Action {
readonly type = UserActionTypes.GetUserFromStorage;
}
export class GetUserFromStorageSuccess implements Action {
readonly type = UserActionTypes.GetUserFromStorageSuccess;
constructor(public payload: User | null) { }
}
export class GetUserFromStorageFail implements Action {
readonly type = UserActionTypes.GetUserFromStorageFail;
constructor(public payload: string) { }
}
Run Code Online (Sandbox Code Playgroud)
减速器:
case UserActionTypes.GetUserFromStorageSuccess:
return {
...state,
user: action.payload,
error: ''
};
case UserActionTypes.GetUserFromStorageFail:
return {
...state,
error: action.payload
};
Run Code Online (Sandbox Code Playgroud)
效果:
@Effect() getUserFromStorage$:
Observable<userActions.GetUserFromStorageSuccess | userActions.GetUserFromStorageFail>
= this.actions$.pipe(
ofType(userActions.UserActionTypes.GetUserFromStorage), …
Run Code Online (Sandbox Code Playgroud) 我是ngrx和Redux风格架构的新手,我在理解如何链接动作/效果方面遇到了问题.一个例子是实现基本功能,例如在用户登录后采取行动.我的核心斗争是在用户登录后要采取的行动将根据应用程序的当前状态而变化 - 用户可能在任何地方在提交登录提示/页面时在应用程序中.
我见过的任何一些例子,一旦用户登录就会发生硬编码效果.在我的场景中,这不符合上述说法,我并不总是希望同样的动作发生.
以下是包含登录组件的主页的一些示例代码.在这种情况下,我希望用户在登录后重定向到"/ buy".
@Component(..)
export class HomePageComponent {
constructor(private store: Store<any>) {
}
public onLoginSubmitted(username, password) {
this.store.dispatch(new loginActions.Login({username, password}));
// once this has happened successfully navigate to /buy
}
}
Run Code Online (Sandbox Code Playgroud)
示例效果
@Injectable()
export class LoginEffects {
......
@Effect()
login$ = this.actions$
.ofType(loginActions.ActionTypes.LOGIN)
.switchMap((data) => {
return this.loginService.login(data.payload)
.map(() => new loginActions.LoginSuccess({loggedIn: true, isLoggingIn: false}))
.catch((error) => {
return of(new loginActions.LoginError({loggedIn: false, isLoggingIn: false}));
});
});
......
}
Run Code Online (Sandbox Code Playgroud)
关于如何解决这个问题,我有几点想法 - 但他们都不是正确的.这些包括
任何人都可以指出我应该如何解决这个问题的正确途径/现有例子吗?
我的问题涉及ngrx 效应和减速器.
在将它放入ngrx存储之前,我需要转换从后端检索的数据.从后端检索的数据是一个普通数组Message
(Message
在我的应用程序中是一个自定义类型):
Message[]
Run Code Online (Sandbox Code Playgroud)
我需要将数组转换为以下内容:
Map<string, Message[]>
Run Code Online (Sandbox Code Playgroud)
基本上我是按对方(收件人或发件人)ID(密钥)对用户的邮件进行分组.
我不知道从哪里执行转换Message[]
到Map<string, Message[]>
:我应该把转型业务逻辑到@Effect或进入减速功能?
ngrx-effects ×10
ngrx ×9
angular ×8
ngrx-store ×5
redux ×2
rxjs ×2
angular5 ×1
javascript ×1
typescript ×1